diff --git a/.env.example b/.env.example
index c6c3cade..23f4d87b 100644
--- a/.env.example
+++ b/.env.example
@@ -1,11 +1,11 @@
-OPENAI_API_KEY="your_openai_api_key_here"
+OPENAI_API_KEY=""
 GOOGLE_API_KEY=""
 ANTHROPIC_API_KEY=""
 AI21_API_KEY="your_api_key_here"
 COHERE_API_KEY="your_api_key_here"
 ALEPHALPHA_API_KEY="your_api_key_here"
 HUGGINFACEHUB_API_KEY="your_api_key_here"
-
+STABILITY_API_KEY="your_api_key_here"
 
 WOLFRAM_ALPHA_APPID="your_wolfram_alpha_appid_here"
 ZAPIER_NLA_API_KEY="your_zapier_nla_api_key_here"
@@ -41,4 +41,7 @@ REDIS_PORT=
 PINECONE_API_KEY=""
 BING_COOKIE=""
 
-PSG_CONNECTION_STRING=""
\ No newline at end of file
+PSG_CONNECTION_STRING=""
+GITHUB_USERNAME=""
+GITHUB_REPO_NAME=""
+GITHUB_TOKEN=""
\ No newline at end of file
diff --git a/.flake8 b/.flake8
index d148ed3e..eedac54c 100644
--- a/.flake8
+++ b/.flake8
@@ -1,2 +1,2 @@
 [flake8]
-extend-ignore = E501, W292, W291
\ No newline at end of file
+extend-ignore = E501, W292, W291, W293
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index c626b001..e3733b98 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,13 +1,14 @@
+---
 # These are supported funding model platforms
 
 github: [kyegomez]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
-custom: #Nothing
+# patreon: # Replace with a single Patreon username
+# open_collective: # Replace with a single Open Collective username
+# ko_fi: # Replace with a single Ko-fi username
+# tidelift: # Replace with a single Tidelift platform-name/package-name
+# community_bridge: # Replace with a single Community Bridge project-name
+# liberapay: # Replace with a single Liberapay username
+# issuehunt: # Replace with a single IssueHunt username
+# otechie: # Replace with a single Otechie username
+# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name
+# custom: #Nothing
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 34b75fb9..b523994a 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,3 +1,4 @@
+---
 # https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates
 
 version: 2
@@ -11,4 +12,3 @@ updates:
     directory: "/"
     schedule:
       interval: "weekly"
-
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 72ccc40a..1fb9d7ec 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -1,12 +1,14 @@
+---
 # this is a config file for the github action labeler
 
 # Add 'label1' to any changes within 'example' folder or any subfolders
 example_change:
-- example/**
+  - example/**
 
 # Add 'label2' to any file changes within 'example2' folder
 example2_change: example2/*
 
-# Add label3 to any change to .txt files within the entire repository. Quotation marks are required for the leading asterisk
+# Add label3 to any change to .txt files within the entire repository.
+# Quotation marks are required for the leading asterisk
 text_files:
-- '**/*.txt'
\ No newline at end of file
+  - '**/*.txt'
diff --git a/.github/workflows/RELEASE.yml b/.github/workflows/RELEASE.yml
index 0abb2ed7..cde08689 100644
--- a/.github/workflows/RELEASE.yml
+++ b/.github/workflows/RELEASE.yml
@@ -22,10 +22,10 @@ jobs:
       - uses: actions/checkout@v4
       - name: Install poetry
         run: pipx install poetry==$POETRY_VERSION
-      - name: Set up Python 3.10
+      - name: Set up Python 3.9
         uses: actions/setup-python@v4
         with:
-          python-version: "3.10"
+          python-version: "3.9"
           cache: "poetry"
       - name: Build project for distribution
         run: poetry build
diff --git a/.github/workflows/code_quality_control.yml b/.github/workflows/code_quality_control.yml
deleted file mode 100644
index a0a49572..00000000
--- a/.github/workflows/code_quality_control.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-name: Linting and Formatting
-
-on:
-  push:
-    branches:
-      - master
-
-jobs:
-  lint_and_format:
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v4
-
-      - name: Set up Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: 3.x
-
-      - name: Install dependencies
-        run: pip install -r requirements.txt
-
-      - name: Find Python files
-        run: find swarms -name "*.py" -type f -exec autopep8 --in-place --aggressive --aggressive {} +
-
-      - name: Push changes
-        uses: ad-m/github-push-action@master
-        with:
-          github_token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/cos_integration.yml b/.github/workflows/cos_integration.yml
deleted file mode 100644
index 3bfb587c..00000000
--- a/.github/workflows/cos_integration.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: Continuous Integration
-
-on:
-  push:
-    branches:
-      - master
-
-jobs:
-  test:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v4
-
-      - name: Set up Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: 3.x
-
-      - name: Install dependencies
-        run: pip install -r requirements.txt
-
-      - name: Run unit tests
-        run: pytest tests/unit
-
-      - name: Run integration tests
-        run: pytest tests/integration
-
-      - name: Run code coverage
-        run: pytest --cov=swarms tests/
-
-      - name: Run linters
-        run: pylint swarms
-
-      - name: Build documentation
-        run: make docs
-
-      - name: Validate documentation
-        run: sphinx-build -b linkcheck docs build/docs
-
-      - name: Run performance tests
-        run: find ./tests -name '*.py' -exec pytest {} \;
\ No newline at end of file
diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml
index 793d8e0e..6ed5bcba 100644
--- a/.github/workflows/docker-image.yml
+++ b/.github/workflows/docker-image.yml
@@ -1,18 +1,19 @@
+---
 name: Docker Image CI
 
-on:
+on:  # yamllint disable-line rule:truthy
   push:
-    branches: [ "master" ]
+    branches: ["master"]
   pull_request:
-    branches: [ "master" ]
+    branches: ["master"]
 
 jobs:
 
   build:
 
     runs-on: ubuntu-latest
-
+    name: Build Docker image
     steps:
-    - uses: actions/checkout@v4
-    - name: Build the Docker image
-      run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
+      - uses: actions/checkout@v4
+      - name: Build the Docker image
+        run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
index beea13b0..17c14973 100644
--- a/.github/workflows/docker-publish.yml
+++ b/.github/workflows/docker-publish.yml
@@ -65,7 +65,7 @@ jobs:
       # https://github.com/docker/metadata-action
       - name: Extract Docker metadata
         id: meta
-        uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
+        uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4 # v5.3.0
         with:
           images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
 
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index a5a31f4b..4cbcf5b5 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -1,4 +1,4 @@
-name: Docs WorkFlow
+name: Docs WorkAgent
 
 on:
   push:
diff --git a/.github/workflows/docs_test.yml b/.github/workflows/docs_test.yml
deleted file mode 100644
index 35d2ca91..00000000
--- a/.github/workflows/docs_test.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name: Documentation Tests
-
-on:
-  push:
-    branches:
-      - master
-
-jobs:
-  test:
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v4
-
-      - name: Set up Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: 3.x
-
-      - name: Install dependencies
-        run: pip install -r requirements.txt
-
-      - name: Build documentation
-        run: make docs
-
-      - name: Validate documentation
-        run: sphinx-build -b linkcheck docs build/docs
\ No newline at end of file
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 97aa4732..8a6f374c 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -1,19 +1,29 @@
+---
 # This is a basic workflow to help you get started with Actions
 
 name: Lint
 
-on: [push, pull_request]
+on: [push, pull_request]  # yamllint disable-line rule:truthy
 
 jobs:
+  yaml-lint:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out source repository
+        uses: actions/checkout@v4
+      - name: yaml Lint
+        uses: ibiqlik/action-yamllint@v3
   flake8-lint:
     runs-on: ubuntu-latest
-    name: Lint
+    name: flake8 Lint
     steps:
       - name: Check out source repository
         uses: actions/checkout@v4
       - name: Set up Python environment
-        uses: actions/setup-python@v4
-        with:
-          python-version: "3.11"
-      - name: flake8 Lint
-        uses: py-actions/flake8@v2
\ No newline at end of file
+        uses: py-actions/flake8@v2
+  ruff-lint:
+    runs-on: ubuntu-latest
+    name: ruff Lint
+    steps:
+      - uses: actions/checkout@v4
+      - uses: chartboost/ruff-action@v1
diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml
deleted file mode 100644
index 216903d5..00000000
--- a/.github/workflows/lints.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-name: Linting
-
-on:
-  push:
-    branches:
-      - master
-
-jobs:
-  lint:
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v4
-
-      - name: Set up Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: 3.x
-
-      - name: Install dependencies
-        run: pip install -r requirements.txt
-
-      - name: Run linters
-        run: pylint swarms
\ No newline at end of file
diff --git a/.github/workflows/pr_request_checks.yml b/.github/workflows/pr_request_checks.yml
index 56b8c1f7..2b91f9a3 100644
--- a/.github/workflows/pr_request_checks.yml
+++ b/.github/workflows/pr_request_checks.yml
@@ -1,3 +1,4 @@
+---
 name: Pull Request Checks
 
 on:
@@ -19,9 +20,11 @@ jobs:
           python-version: 3.x
 
       - name: Install dependencies
-        run: pip install -r requirements.txt
+        run: |
+          pip install -r requirements.txt
+          pip install pytest 
 
       - name: Run tests and checks
         run: |
-          find tests/ -name "*.py" | xargs pytest
-          pylint swarms
\ No newline at end of file
+          pytest
+          pylint swarms
diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
deleted file mode 100644
index 3f3ba2e2..00000000
--- a/.github/workflows/pylint.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Pylint
-
-on: [push]
-
-jobs:
-  build:
-    runs-on: ubuntu-latest
-    strategy:
-      matrix:
-        python-version: ["3.8", "3.9", "3.10"]
-    steps:
-    - uses: actions/checkout@v4
-    - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v4
-      with:
-        python-version: ${{ matrix.python-version }}
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install pylint
-    - name: Analysing the code with pylint
-      run: |
-        pylint $(git ls-files '*.py')
diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml
deleted file mode 100644
index 1f634309..00000000
--- a/.github/workflows/python-app.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-# This workflow will install Python dependencies, run tests and lint with a single version of Python
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
-
-name: Python application
-
-on:
-  push:
-    branches: [ "master" ]
-  pull_request:
-    branches: [ "master" ]
-
-permissions:
-  contents: read
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v4
-    - name: Set up Python 3.10
-      uses: actions/setup-python@v4
-      with:
-        python-version: "3.10"
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install flake8 pytest
-        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
-    - name: Lint with flake8
-      run: |
-        # stop the build if there are Python syntax errors or undefined names
-        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
-        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
-        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
-    - name: Test with pytest
-      run: |
-        pytest
diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml
index b8e0a17a..fab4f817 100644
--- a/.github/workflows/python-package.yml
+++ b/.github/workflows/python-package.yml
@@ -19,9 +19,9 @@ jobs:
         python-version: ["3.7", "3.9", "3.10", "3.11"]
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v3
+      uses: actions/setup-python@v4
       with:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
@@ -38,4 +38,4 @@ jobs:
         flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
     - name: Test with pytest
       run: |
-        find ./tests -name '*.py' -exec pytest {} \;
+        pytest
\ No newline at end of file
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
index c8f4ba0c..81df64a3 100644
--- a/.github/workflows/python-publish.yml
+++ b/.github/workflows/python-publish.yml
@@ -1,7 +1,7 @@
-
+---
 name: Upload Python Package
 
-on:
+on:  # yamllint disable-line rule:truthy
   release:
     types: [published]
 
@@ -14,19 +14,19 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-    - uses: actions/checkout@v4
-    - name: Set up Python
-      uses: actions/setup-python@v4
-      with:
-        python-version: '3.x'
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install build
-    - name: Build package
-      run: python -m build
-    - name: Publish package
-      uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e
-      with:
-        user: __token__
-        password: ${{ secrets.PYPI_API_TOKEN }}
\ No newline at end of file
+      - uses: actions/checkout@v4
+      - name: Set up Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: '3.x'
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install build
+      - name: Build package
+        run: python -m build
+      - name: Publish package
+        uses: pypa/gh-action-pypi-publish@2f6f737ca5f74c637829c0f5c3acd0e29ea5e8bf
+        with:
+          user: __token__
+          password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
deleted file mode 100644
index 9b09cfa9..00000000
--- a/.github/workflows/quality.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Quality
-
-on:
-  push:
-    branches: [ "master" ]
-  pull_request:
-    branches: [ "master" ]
-
-jobs:
-  lint:
-    runs-on: ubuntu-latest
-    strategy:
-      fail-fast: false
-    steps:
-      - name: Checkout actions
-        uses: actions/checkout@v4
-        with:
-          fetch-depth: 0
-      - name: Init environment 
-        uses: ./.github/actions/init-environment 
-      - name: Run linter
-        run: |
-          pylint `git diff --name-only --diff-filter=d origin/master HEAD | grep -E '\.py$' | tr '\n' ' '`
\ No newline at end of file
diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
deleted file mode 100644
index ef06d34a..00000000
--- a/.github/workflows/ruff.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: Ruff
-on: [ push, pull_request ]
-jobs:
-  ruff:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-      - uses: chartboost/ruff-action@v1
diff --git a/.github/workflows/run_test.yml b/.github/workflows/run_test.yml
deleted file mode 100644
index 172dc64b..00000000
--- a/.github/workflows/run_test.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Python application test
-
-on: [push]
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v4
-    - name: Set up Python 3.8
-      uses: actions/setup-python@v4
-      with:
-        python-version: 3.8
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install pytest
-        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
-    - name: Run tests with pytest
-      run: |
-        find tests/ -name "*.py" | xargs pytest
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 65dc68d9..d9dafc76 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,3 +1,4 @@
+---
 name: test
 
 on:
@@ -9,7 +10,67 @@ on:
 env:
   POETRY_VERSION: "1.4.2"
 
-jobs:
+  test:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version:
+          - "3.8"
+          - "3.9"
+          - "3.10"
+          - "3.11"
+        test_type:
+          - "core"
+          - "extended"
+    steps:
+      - uses: actions/checkout@v4
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: "snok/install-poetry@v1"
+        with:
+          python-version: ${{ matrix.python-version }}
+          poetry-version: "1.4.2"
+          cache-key: ${{ matrix.test_type }}
+          install-command: |
+              if [ "${{ matrix.test_type }}" == "core" ]; then
+                echo "Running core tests, installing dependencies with poetry..."
+                poetry install
+              else
+                echo "Running extended tests, installing dependencies with poetry..."
+                poetry install -E extended_testing
+              fi
+      - name: Run ${{matrix.test_type}} tests
+        run: |
+          if [ "${{ matrix.test_type }}" == "core" ]; then
+            make test
+          else
+            make extended_tests
+          fi
+        shell: bash
+    name: Python ${{ matrix.python-version }} ${{ matrix.test_type }}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: "./.github/actions/poetry_setup"
+        with:
+          python-version: ${{ matrix.python-version }}
+          poetry-version: "1.4.2"
+          cache-key: ${{ matrix.test_type }}
+          install-command: |
+              if [ "${{ matrix.test_type }}" == "core" ]; then
+                echo "Running core tests, installing dependencies with poetry..."
+                poetry install
+              else
+                echo "Running extended tests, installing dependencies with poetry..."
+                poetry install -E extended_testing
+              fi
+      - name: Run ${{matrix.test_type}} tests
+        run: |
+          if [ "${{ matrix.test_type }}" == "core" ]; then
+            make test
+          else
+            make extended_tests
+          fi
+        shell: bash
   build:
     runs-on: ubuntu-latest
     strategy:
diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml
index c2c805f5..ae572d22 100644
--- a/.github/workflows/testing.yml
+++ b/.github/workflows/testing.yml
@@ -19,7 +19,9 @@ jobs:
           python-version: 3.x
 
       - name: Install dependencies
-        run: pip install -r requirements.txt
+        run: |
+          pip install -r requirements.txt
+          pip install pytest
 
       - name: Run unit tests
-        run: find tests/ -name "*.py" | xargs pytest
\ No newline at end of file
+        run: pytest
\ No newline at end of file
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 42ac2271..0a1985a7 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -18,16 +18,18 @@ jobs:
     - name: Setup Python
       uses: actions/setup-python@v4
       with:
-        python-version: '3.10'
+        python-version: '3.9'
 
     - name: Install dependencies
-      run: pip install -r requirements.txt
+      run: |
+        pip install -r requirements.txt
+        pip install pytest
 
     - name: Run Python unit tests
-      run: python3 -m unittest tests/
+      run: pytest
 
     - name: Verify that the Docker image for the action builds
       run: docker build . --file Dockerfile
 
     - name: Verify integration test results
-      run: find tests/ -name "*.py" | xargs pytest
+      run: pytest
diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml
index 25edc27c..3dcd5bb1 100644
--- a/.github/workflows/welcome.yml
+++ b/.github/workflows/welcome.yml
@@ -1,4 +1,4 @@
-name: Welcome WorkFlow
+name: Welcome WorkAgent
 
 on:
   issues:
@@ -12,7 +12,7 @@ jobs:
     permissions: write-all
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/first-interaction@v1.2.0
+      - uses: actions/first-interaction@v1.3.0
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
           issue-message: "Hello there, thank you for opening an Issue ! πŸ™πŸ» The team was notified and they will get back to you asap."
diff --git a/.gitignore b/.gitignore
index 8f8a98a8..6fc93744 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ video/
 dataframe/
 
 static/generated
+runs
 swarms/__pycache__
 venv
 .DS_Store
@@ -186,4 +187,5 @@ cython_debug/
 #  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
 #  and can be added to the global gitignore or merged into this file.  For a more nuclear
 #  option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
\ No newline at end of file
+#.idea/
+.vscode/settings.json
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ae0a4fc0..0c936705 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,7 +7,7 @@ repos:
     rev: 'v0.0.255'
     hooks:
       - id: ruff
-        args: [--fix]
+        args: [----unsafe-fixes]
   - repo: https://github.com/nbQA-dev/nbQA
     rev: 1.6.3
     hooks:
diff --git a/.readthedocs.yml b/.readthedocs.yml
index fbdc74ec..e3e74fad 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -10,4 +10,4 @@ mkdocs:
 
 python:
    install:
-   - requirements: requirements.txt
\ No newline at end of file
+   - requirements: requirements.txt
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 04f0f593..21f4b51c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,6 +20,12 @@ Swarms is designed to provide modular building blocks to build scalable swarms o
 
 Before you contribute a new feature, consider submitting an Issue to discuss the feature so the community can weigh in and assist.
 
+### Requirements:
+- New class and or function Module with documentation in docstrings with error handling
+- Tests using pytest in tests folder in the same module folder
+- Documentation in the docs/swarms/module_name folder and then added into the mkdocs.yml
+
+
 ## How to Contribute Changes
 
 First, fork this repository to your own GitHub account. Click "fork" in the top corner of the `swarms` repository to get started:
@@ -43,11 +49,29 @@ git push -u origin main
 ```
 
 ## 🎨 Code quality
+- Follow the following guide on code quality a python guide or your PR will most likely be overlooked: [CLICK HERE](https://google.github.io/styleguide/pyguide.html)
+
+
 
 ### Pre-commit tool
 
 This project utilizes the [pre-commit](https://pre-commit.com/) tool to maintain code quality and consistency. Before submitting a pull request or making any commits, it is important to run the pre-commit tool to ensure that your changes meet the project's guidelines.
 
+
+- Install pre-commit (https://pre-commit.com/)
+
+```bash
+pip install pre-commit
+```
+
+- Check that it's installed
+
+```bash
+pre-commit --version
+```
+
+Now when you make a git commit, the black code formatter and ruff linter will run.
+
 Furthermore, we have integrated a pre-commit GitHub Action into our workflow. This means that with every pull request opened, the pre-commit checks will be automatically enforced, streamlining the code review process and ensuring that all contributions adhere to our quality standards.
 
 To run the pre-commit tool, follow these steps:
@@ -60,6 +84,7 @@ To run the pre-commit tool, follow these steps:
 
 4. You can also install pre-commit as a git hook by execute `pre-commit install`. Every time you made `git commit` pre-commit run automatically for you.
 
+
 ### Docstrings
 
 All new functions and classes in `swarms` should include docstrings. This is a prerequisite for any new functions and classes to be added to the library.
@@ -98,13 +123,13 @@ You can learn more about mkdocs on the [mkdocs website](https://www.mkdocs.org/)
 
 ## πŸ§ͺ tests
 - Run all the tests in the tests folder
-`find ./tests -name '*.py' -exec pytest {} \;`
-
+   ```pytest```
+   
 ## Code Quality
-`quality.sh` runs 4 different code formatters for ultra reliable code cleanup using Autopep8, Black, Ruff, YAPF
+`code-quality.sh` runs 4 different code formatters for ultra reliable code cleanup using Autopep8, Black, Ruff, YAPF
 1. Open your terminal.
 
-2. Change directory to where `quality.sh` is located using `cd` command:
+2. Change directory to where `code-quality.sh` is located using `cd` command:
    ```sh
    cd /path/to/directory
    ```
@@ -116,17 +141,17 @@ You can learn more about mkdocs on the [mkdocs website](https://www.mkdocs.org/)
 
 4. Run the script:
    ```sh
-   ./quality.sh
+   ./code-quality.sh
    ```
    
 If the script requires administrative privileges, you might need to run it with `sudo`:
 ```sh
-sudo ./quality.sh
+sudo ./code-quality.sh
 ```
 
-Please replace `/path/to/directory` with the actual path where the `quality.sh` script is located on your system.
+Please replace `/path/to/directory` with the actual path where the `code-quality.sh` script is located on your system.
 
-If you're asking for a specific content or functionality inside `quality.sh` related to YAPF or other code quality tools, you would need to edit the `quality.sh` script to include the desired commands, such as running YAPF on a directory. The contents of `quality.sh` would dictate exactly what happens when you run it.
+If you're asking for a specific content or functionality inside `code-quality.sh` related to YAPF or other code quality tools, you would need to edit the `code-quality.sh` script to include the desired commands, such as running YAPF on a directory. The contents of `code-quality.sh` would dictate exactly what happens when you run it.
 
 
 ## πŸ“„ license
diff --git a/Developers.md b/Developers.md
deleted file mode 100644
index ca7fda93..00000000
--- a/Developers.md
+++ /dev/null
@@ -1,21 +0,0 @@
-Developers
-
-Install pre-commit (https://pre-commit.com/)
-
-```bash
-pip install pre-commit
-```
-
-Check that it's installed
-
-```bash
-pre-commit --versioni
-```
-
-This repository already has a pre-commit configuration. To install the hooks, run:
-
-```bash
-pre-commit install
-```
-
-Now when you make a git commit, the black code formatter and ruff linter will run.
diff --git a/README.md b/README.md
index 5ef0678b..3ce706e6 100644
--- a/README.md
+++ b/README.md
@@ -22,55 +22,46 @@ Swarms is a modular framework that enables reliable and useful multi-agent colla
 ---
 
 ## Usage
-### Example in Colab:
 
-<a target="_blank" href="https://colab.research.google.com/github/kyegomez/swarms/blob/master/playground/swarms_example.ipynb">
+Run example in Collab: <a target="_blank" href="https://colab.research.google.com/github/kyegomez/swarms/blob/master/playground/swarms_example.ipynb">
 <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
-</a> Run example in Colab, using your OpenAI API key. 
+</a>
 
-### `Flow` Example
+### `Agent` Example
 - Reliable Structure that provides LLMS autonomy
 - Extremely Customizeable with stopping conditions, interactivity, dynamical temperature, loop intervals, and so much more
-- Enterprise Grade + Production Grade: `Flow` is designed and optimized for automating real-world tasks at scale!
+- Enterprise Grade + Production Grade: `Agent` is designed and optimized for automating real-world tasks at scale!
 
 ```python
+import os
 
+from dotenv import load_dotenv
+
+# Import the OpenAIChat model and the Agent struct
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
+
+# Load the environment variables
+load_dotenv()
 
-api_key = ""
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
 
-# Initialize the language model, this model can be swapped out with Anthropic, ETC, Huggingface Models like Mistral, ETC
+# Initialize the language model
 llm = OpenAIChat(
-    # model_name="gpt-4"
-    openai_api_key=api_key,
     temperature=0.5,
-    # max_tokens=100,
+    model_name="gpt-4",
+    openai_api_key=api_key,
+    max_tokens=4000
 )
 
-## Initialize the workflow
-flow = Flow(
-    llm=llm,
-    max_loops=2,
-    dashboard=True,
-    # stopping_condition=None,  # You can define a stopping condition as needed.
-    # loop_interval=1,
-    # retry_attempts=3,
-    # retry_interval=1,
-    # interactive=False,  # Set to 'True' for interactive mode.
-    # dynamic_temperature=False,  # Set to 'True' for dynamic temperature handling.
-)
 
-# out = flow.load_state("flow_state.json")
-# temp = flow.dynamic_temperature()
-# filter = flow.add_response_filter("Trump")
-out = flow.run("Generate a 10,000 word blog on health and wellness.")
-# out = flow.validate_response(out)
-# out = flow.analyze_feedback(out)
-# out = flow.print_history_and_memory()
-# # out = flow.save_state("flow_state.json")
-# print(out)
+## Initialize the workflow
+agent = Agent(llm=llm, max_loops=1, autosave=True, dashboard=True)
 
+# Run the workflow on a task
+out = agent.run("Generate a 10,000 word blog on health and wellness.")
+print(out)
 
 
 ```
@@ -80,52 +71,51 @@ out = flow.run("Generate a 10,000 word blog on health and wellness.")
 ### `SequentialWorkflow`
 - A Sequential swarm of autonomous agents where each agent's outputs are fed into the next agent
 - Save and Restore Workflow states!
-- Integrate Flow's with various LLMs and Multi-Modality Models
+- Integrate Agent's with various LLMs and Multi-Modality Models
 
 ```python
-from swarms.models import OpenAIChat, BioGPT, Anthropic
-from swarms.structs import Flow
+import os 
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
+from dotenv import load_dotenv
 
+load_dotenv()
 
-# Example usage
-api_key = (
-    ""  # Your actual API key here
-)
+# Load the environment variables
+api_key = os.getenv("OPENAI_API_KEY")
 
-# Initialize the language flow
+
+# Initialize the language agent
 llm = OpenAIChat(
-    openai_api_key=api_key,
     temperature=0.5,
-    max_tokens=3000,
+    model_name="gpt-4",
+    openai_api_key=api_key,
+    max_tokens=4000
 )
 
-biochat = BioGPT()
 
-# Use Anthropic
-anthropic = Anthropic()
-
-# Initialize the agent with the language flow
-agent1 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize the agent with the language agent
+agent1 = Agent(llm=llm, max_loops=1)
 
 # Create another agent for a different task
-agent2 = Flow(llm=llm, max_loops=1, dashboard=False)
+agent2 = Agent(llm=llm, max_loops=1)
 
 # Create another agent for a different task
-agent3 = Flow(llm=biochat, max_loops=1, dashboard=False)
-
-# agent4 = Flow(llm=anthropic, max_loops="auto")
+agent3 = Agent(llm=llm, max_loops=1)
 
 # Create the workflow
 workflow = SequentialWorkflow(max_loops=1)
 
 # Add tasks to the workflow
-workflow.add("Generate a 10,000 word blog on health and wellness.", agent1)
+workflow.add(
+    agent1, "Generate a 10,000 word blog on health and wellness.", 
+)
 
 # Suppose the next task takes the output of the first task as input
-workflow.add("Summarize the generated blog", agent2)
-
-workflow.add("Create a references sheet of materials for the curriculm", agent3)
+workflow.add(
+    agent2, "Summarize the generated blog",
+)
 
 # Run the workflow
 workflow.run()
@@ -134,6 +124,54 @@ workflow.run()
 for task in workflow.tasks:
     print(f"Task: {task.description}, Result: {task.result}")
 
+
+```
+
+## `Multi Modal Autonomous Agents`
+- Run the agent with multiple modalities useful for various real-world tasks in manufacturing, logistics, and health.
+
+```python
+# Description: This is an example of how to use the Agent class to run a multi-modal workflow
+import os
+from dotenv import load_dotenv
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.structs import Agent
+
+# Load the environment variables
+load_dotenv()
+
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
+
+# Initialize the language model
+llm = GPT4VisionAPI(
+    openai_api_key=api_key,
+    max_tokens=500,
+)
+
+# Initialize the task
+task = (
+    "Analyze this image of an assembly line and identify any issues such as"
+    " misaligned parts, defects, or deviations from the standard assembly"
+    " process. IF there is anything unsafe in the image, explain why it is"
+    " unsafe and how it could be improved."
+)
+img = "assembly_line.jpg"
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm,
+    max_loops="auto",
+    autosave=True,
+    dashboard=True,
+    multi_modal=True
+)
+
+# Run the workflow on a task
+out = agent.run(task=task, img=img)
+print(out)
+
+
 ```
 
 ---
@@ -213,8 +251,16 @@ Swarms framework is not just a tool but a robust, scalable, and secure partner i
 - For documentation, go here, [swarms.apac.ai](https://swarms.apac.ai)
 
 
-## Contribute
-- We're always looking for contributors to help us improve and expand this project. If you're interested, please check out our [Contributing Guidelines](CONTRIBUTING.md) and our [contributing board](https://github.com/users/kyegomez/projects/1)
+## 🫢 Contributions:
+
+Swarms is an open-source project, and contributions are welcome. If you want to contribute, you can create new features, fix bugs, or improve the infrastructure. Please refer to the [CONTRIBUTING.md](https://github.com/kyegomez/swarms/blob/master/CONTRIBUTING.md) and our [contributing board](https://github.com/users/kyegomez/projects/1) file in the repository for more information on how to contribute.
+
+To see how to contribute, visit [Contribution guidelines](https://github.com/kyegomez/swarms/blob/master/CONTRIBUTING.md)
+
+<a href="https://github.com/kyegomez/swarms/graphs/contributors">
+  <img src="https://contrib.rocks/image?repo=kyegomez/swarms" />
+</a>
+
 
 ## Community
 - [Join the Swarms community on Discord!](https://discord.gg/AJazBmhKnr)
diff --git a/docs/examples/flow.md b/docs/examples/flow.md
index 454bd244..92842491 100644
--- a/docs/examples/flow.md
+++ b/docs/examples/flow.md
@@ -1,7 +1,7 @@
 # Reliable Enterprise-Grade Autonomous Agents in Less Than 5 lines of Code
 ========================================================================
 
-Welcome to the walkthrough guide for beginners on using the "Flow" feature within the Swarms framework. This guide is designed to help you understand and utilize the capabilities of the Flow class for seamless and reliable interactions with autonomous agents.
+Welcome to the walkthrough guide for beginners on using the "Agent" feature within the Swarms framework. This guide is designed to help you understand and utilize the capabilities of the Agent class for seamless and reliable interactions with autonomous agents.
 
 ## Official Swarms Links
 =====================
@@ -21,27 +21,27 @@ Now let's begin...
 ## [Table of Contents](https://github.com/kyegomez/swarms)
 ===========================================================================================================
 
-1.  Introduction to Swarms Flow Module
+1.  Introduction to Swarms Agent Module
 
 -   1.1 What is Swarms?
--   1.2 Understanding the Flow Module
+-   1.2 Understanding the Agent Module
 
 2. Setting Up Your Development Environment
 
 -   2.1 Installing Required Dependencies
 -   2.2 API Key Setup
--   2.3 Creating Your First Flow
+-   2.3 Creating Your First Agent
 
-3. Creating Your First Flow
+3. Creating Your First Agent
 
 -   3.1 Importing Necessary Libraries
 -   3.2 Defining Constants
--   3.3 Initializing the Flow Object
+-   3.3 Initializing the Agent Object
 -   3.4 Initializing the Language Model
--   3.5 Running Your Flow
--   3.6 Understanding Flow Options
+-   3.5 Running Your Agent
+-   3.6 Understanding Agent Options
 
-4. Advanced Flow Concepts
+4. Advanced Agent Concepts
 
 -   4.1 Custom Stopping Conditions
 -   4.2 Dynamic Temperature Handling
@@ -50,10 +50,10 @@ Now let's begin...
 -   4.5 Response Filtering
 -   4.6 Interactive Mode
 
-5. Saving and Loading Flows
+5. Saving and Loading Agents
 
--   5.1 Saving Flow State
--   5.2 Loading a Saved Flow
+-   5.1 Saving Agent State
+-   5.2 Loading a Saved Agent
 
 6. Troubleshooting and Tips
 
@@ -62,7 +62,7 @@ Now let's begin...
 
 7. Conclusion
 
-## [1. Introduction to Swarms Flow Module](https://github.com/kyegomez/swarms)
+## [1. Introduction to Swarms Agent Module](https://github.com/kyegomez/swarms)
 ===================================================================================================================================================
 
 ### [1.1 What is Swarms?](https://github.com/kyegomez/swarms)
@@ -70,23 +70,23 @@ Now let's begin...
 
 Swarms is a powerful framework designed to provide tools and capabilities for working with language models and automating various tasks. It allows developers to interact with language models seamlessly.
 
-## 1.2 Understanding the Flow Feature
+## 1.2 Understanding the Agent Feature
 ==================================
 
-### [What is the Flow Feature?](https://github.com/kyegomez/swarms)
+### [What is the Agent Feature?](https://github.com/kyegomez/swarms)
 --------------------------------------------------------------------------------------------------------------------------
 
-The Flow feature is a powerful component of the Swarms framework that allows developers to create a sequential, conversational interaction with AI language models. It enables developers to build multi-step conversations, generate long-form content, and perform complex tasks using AI. The Flow class provides autonomy to language models, enabling them to generate responses in a structured manner.
+The Agent feature is a powerful component of the Swarms framework that allows developers to create a sequential, conversational interaction with AI language models. It enables developers to build multi-step conversations, generate long-form content, and perform complex tasks using AI. The Agent class provides autonomy to language models, enabling them to generate responses in a structured manner.
 
 ### [Key Concepts](https://github.com/kyegomez/swarms)
 -------------------------------------------------------------------------------------------------
 
-Before diving into the practical aspects, let's clarify some key concepts related to the Flow feature:
+Before diving into the practical aspects, let's clarify some key concepts related to the Agent feature:
 
--   Flow: A Flow is an instance of the Flow class that represents an ongoing interaction with an AI language model. It consists of a series of steps and responses.
--   Stopping Condition: A stopping condition is a criterion that, when met, allows the Flow to stop generating responses. This can be user-defined and can depend on the content of the responses.
+-   Agent: A Agent is an instance of the Agent class that represents an ongoing interaction with an AI language model. It consists of a series of steps and responses.
+-   Stopping Condition: A stopping condition is a criterion that, when met, allows the Agent to stop generating responses. This can be user-defined and can depend on the content of the responses.
 -   Loop Interval: The loop interval specifies the time delay between consecutive interactions with the AI model.
--   Retry Mechanism: In case of errors or failures during AI model interactions, the Flow can be configured to make multiple retry attempts with a specified interval.
+-   Retry Mechanism: In case of errors or failures during AI model interactions, the Agent can be configured to make multiple retry attempts with a specified interval.
 -   Interactive Mode: Interactive mode allows developers to have a back-and-forth conversation with the AI model, making it suitable for real-time interactions.
 
 ## [2. Setting Up Your Development Environment](https://github.com/kyegomez/swarms)
@@ -95,38 +95,38 @@ Before diving into the practical aspects, let's clarify some key concepts relate
 ### [2.1 Installing Required Dependencies](https://github.com/kyegomez/swarms)
 ------------------------------------------------------------------------------------------------------------------------------------------------
 
-Before you can start using the Swarms Flow module, you need to set up your development environment. First, you'll need to install the necessary dependencies, including Swarms itself.
+Before you can start using the Swarms Agent module, you need to set up your development environment. First, you'll need to install the necessary dependencies, including Swarms itself.
 
 # Install Swarms and required libraries
 `pip3 install --upgrade swarms`
 
-## [2. Creating Your First Flow](https://github.com/kyegomez/swarms)
+## [2. Creating Your First Agent](https://github.com/kyegomez/swarms)
 -----------------------------------------------------------------------------------------------------------------------------
 
-Now, let's create your first Flow. A Flow represents a chain-like structure that allows you to engage in multi-step conversations with language models. The Flow structure is what gives an LLM autonomy. It's the Mitochondria of an autonomous agent.
+Now, let's create your first Agent. A Agent represents a chain-like structure that allows you to engage in multi-step conversations with language models. The Agent structure is what gives an LLM autonomy. It's the Mitochondria of an autonomous agent.
 
 # Import necessary modules
 ```python
 from swarms.models import OpenAIChat # Zephr, Mistral
-from swarms.structs import Flow
+from swarms.structs import Agent
 
 api_key = ""# Initialize the language model (LLM)
-llm = OpenAIChat(openai_api_key=api_key, temperature=0.5, max_tokens=3000)# Initialize the Flow object
+llm = OpenAIChat(openai_api_key=api_key, temperature=0.5, max_tokens=3000)# Initialize the Agent object
 
-flow = Flow(llm=llm, max_loops=5)# Run the flow
-out = flow.run("Create an financial analysis on the following metrics")
+agent = Agent(llm=llm, max_loops=5)# Run the agent
+out = agent.run("Create an financial analysis on the following metrics")
 print(out)
 
 ```
 
-### [3. Initializing the Flow Object](https://github.com/kyegomez/swarms)
+### [3. Initializing the Agent Object](https://github.com/kyegomez/swarms)
 ----------------------------------------------------------------------------------------------------------------------------------------
 
-Create a Flow object that will be the backbone of your conversational flow.
+Create a Agent object that will be the backbone of your conversational agent.
 
 ```python
-# Initialize the Flow object
-flow = Flow(
+# Initialize the Agent object
+agent = Agent(
     llm=llm,
     max_loops=5,
     stopping_condition=None,  # You can define custom stopping conditions
@@ -142,7 +142,7 @@ flow = Flow(
 ### [3.2 Initializing the Language Model](https://github.com/kyegomez/swarms)
 ----------------------------------------------------------------------------------------------------------------------------------------------
 
-Initialize the language model (LLM) that your Flow will interact with. In this example, we're using OpenAI's GPT-3 as the LLM.
+Initialize the language model (LLM) that your Agent will interact with. In this example, we're using OpenAI's GPT-3 as the LLM.
 
 -   You can also use `Mistral` or `Zephr` or any of other models!
 
@@ -155,16 +155,16 @@ llm = OpenAIChat(
 )
 ```
 
-### [3.3 Running Your Flow](https://github.com/kyegomez/swarms)
+### [3.3 Running Your Agent](https://github.com/kyegomez/swarms)
 ------------------------------------------------------------------------------------------------------------------
 
-Now, you're ready to run your Flow and start interacting with the language model.
+Now, you're ready to run your Agent and start interacting with the language model.
 
 If you are using a multi modality model, you can pass in the image path as another parameter
 
 ```
-# Run your Flow
-out = flow.run(
+# Run your Agent
+out = agent.run(
     "Generate a 10,000 word blog on health and wellness.",
     # "img.jpg" , Image path for multi-modal models
     )
@@ -174,14 +174,14 @@ print(out)
 
 This code will initiate a conversation with the language model, and you'll receive responses accordingly.
 
-## [4. Advanced Flow Concepts](https://github.com/kyegomez/swarms)
+## [4. Advanced Agent Concepts](https://github.com/kyegomez/swarms)
 ===========================================================================================================================
 
-In this section, we'll explore advanced concepts that can enhance your experience with the Swarms Flow module.
+In this section, we'll explore advanced concepts that can enhance your experience with the Swarms Agent module.
 
 ### [4.1 Custom Stopping Conditions](https://github.com/kyegomez/swarms)
 
-You can define custom stopping conditions for your Flow. For example, you might want the Flow to stop when a specific word is mentioned in the response.
+You can define custom stopping conditions for your Agent. For example, you might want the Agent to stop when a specific word is mentioned in the response.
 
 # Custom stopping condition example
 ```python
@@ -189,16 +189,16 @@ def stop_when_repeats(response: str) -> bool:
     return "Stop" in response.lower()
 ```
 
-# Set the stopping condition in your Flow
-```flow.stopping_condition = stop_when_repeats```
+# Set the stopping condition in your Agent
+```agent.stopping_condition = stop_when_repeats```
 
 ### [4.2 Dynamic Temperature Handling](https://github.com/kyegomez/swarms)
 ----------------------------------------------------------------------------------------------------------------------------------------
 
 Dynamic temperature handling allows you to adjust the temperature attribute of the language model during the conversation.
 
-# Enable dynamic temperature handling in your Flow
-`flow.dynamic_temperature = True`
+# Enable dynamic temperature handling in your Agent
+`agent.dynamic_temperature = True`
 
 This feature randomly changes the temperature attribute for each loop, providing a variety of responses.
 
@@ -208,7 +208,7 @@ This feature randomly changes the temperature attribute for each loop, providing
 You can provide feedback on responses generated by the language model using the `provide_feedback` method.
 
 - Provide feedback on a response
-`flow.provide_feedback("The response was helpful.")`
+`agent.provide_feedback("The response was helpful.")`
 
 This feedback can be valuable for improving the quality of responses.
 
@@ -219,8 +219,8 @@ In case of errors or issues during conversation, you can implement a retry mecha
 
 # Set the number of retry attempts and interval
 ```python
-flow.retry_attempts = 3
-flow.retry_interval = 1  # in seconds
+agent.retry_attempts = 3
+agent.retry_interval = 1  # in seconds
 ```
 ### [4.5 Response Filtering](https://github.com/kyegomez/swarms)
 --------------------------------------------------------------------------------------------------------------------
@@ -229,38 +229,38 @@ You can add response filters to filter out certain words or phrases from the res
 
 # Add a response filter
 ```python
-flow.add_response_filter("inappropriate_word")
+agent.add_response_filter("inappropriate_word")
 ```
 This helps in controlling the content generated by the language model.
 
 ### [4.6 Interactive Mode](https://github.com/kyegomez/swarms)
 ----------------------------------------------------------------------------------------------------------------
 
-Interactive mode allows you to have a back-and-forth conversation with the language model. When enabled, the Flow will prompt for user input after each response.
+Interactive mode allows you to have a back-and-forth conversation with the language model. When enabled, the Agent will prompt for user input after each response.
 
 # Enable interactive mode
-`flow.interactive = True`
+`agent.interactive = True`
 
 This is useful for real-time conversations with the model.
 
-## [5. Saving and Loading Flows](https://github.com/kyegomez/swarms)
+## [5. Saving and Loading Agents](https://github.com/kyegomez/swarms)
 ===============================================================================================================================
 
-### [5.1 Saving Flow State](https://github.com/kyegomez/swarms)
+### [5.1 Saving Agent State](https://github.com/kyegomez/swarms)
 ------------------------------------------------------------------------------------------------------------------
 
-You can save the state of your Flow, including the conversation history, for future use.
+You can save the state of your Agent, including the conversation history, for future use.
 
-# Save the Flow state to a file
-`flow.save("path/to/flow_state.json")``
+# Save the Agent state to a file
+`agent.save("path/to/flow_state.json")``
 
-### [5.2 Loading a Saved Flow](https://github.com/kyegomez/swarms)
+### [5.2 Loading a Saved Agent](https://github.com/kyegomez/swarms)
 ------------------------------------------------------------------------------------------------------------------------
 
-To continue a conversation or reuse a Flow, you can load a previously saved state.
+To continue a conversation or reuse a Agent, you can load a previously saved state.
 
-# Load a saved Flow state
-`flow.load("path/to/flow_state.json")``
+# Load a saved Agent state
+`agent.load("path/to/flow_state.json")``
 
 ## [6. Troubleshooting and Tips](https://github.com/kyegomez/swarms)
 ===============================================================================================================================
@@ -271,17 +271,17 @@ To continue a conversation or reuse a Flow, you can load a previously saved stat
 You can analyze the feedback provided during the conversation to identify issues and improve the quality of interactions.
 
 # Analyze feedback
-`flow.analyze_feedback()`
+`agent.analyze_feedback()`
 
 ### [6.2 Troubleshooting Common Issues](https://github.com/kyegomez/swarms)
 ------------------------------------------------------------------------------------------------------------------------------------------
 
 If you encounter issues during conversation, refer to the troubleshooting section for guidance on resolving common problems.
 
-# [7. Conclusion: Empowering Developers with Swarms Framework and Flow Structure for Automation](https://github.com/kyegomez/swarms)
+# [7. Conclusion: Empowering Developers with Swarms Framework and Agent Structure for Automation](https://github.com/kyegomez/swarms)
 ================================================================================================================================================================================================================================================================
 
-In a world where digital tasks continue to multiply and diversify, the need for automation has never been more critical. Developers find themselves at the forefront of this automation revolution, tasked with creating reliable solutions that can seamlessly handle an array of digital tasks. Enter the Swarms framework and the Flow structure, a dynamic duo that empowers developers to build autonomous agents capable of efficiently and effectively automating a wide range of digital tasks.
+In a world where digital tasks continue to multiply and diversify, the need for automation has never been more critical. Developers find themselves at the forefront of this automation revolution, tasked with creating reliable solutions that can seamlessly handle an array of digital tasks. Enter the Swarms framework and the Agent structure, a dynamic duo that empowers developers to build autonomous agents capable of efficiently and effectively automating a wide range of digital tasks.
 
 [The Automation Imperative](https://github.com/kyegomez/swarms)
 ---------------------------------------------------------------------------------------------------------------------------
@@ -300,7 +300,7 @@ One of the standout features of Swarms is its seamless integration with state-of
 
 By leveraging Swarms, developers can effortlessly incorporate these language models into their applications and workflows. For instance, they can build chatbots that provide intelligent responses to customer inquiries or generate lengthy documents with minimal manual intervention. This not only saves time but also enhances overall productivity.
 
-[2. Multi-Step Conversational Flows](https://github.com/kyegomez/swarms)
+[2. Multi-Step Conversational Agents](https://github.com/kyegomez/swarms)
 ---------------------------------------------------------------------------------------------------------------------------------------------
 
 Swarms excels in orchestrating multi-step conversational flows. Developers can define intricate sequences of interactions, where the system generates responses, and users provide input at various stages. This functionality is a game-changer for building chatbots, virtual assistants, or any application requiring dynamic and context-aware conversations.
@@ -324,58 +324,58 @@ Swarms encourages the collection of feedback on generated responses. Developers
 
 Error handling is a critical aspect of any automation framework. Swarms simplifies this process by offering a retry mechanism. In case of errors or issues during conversations, developers can configure the framework to attempt generating responses again, ensuring robust and resilient automation.
 
-[6. Saving and Loading Flows](https://github.com/kyegomez/swarms)
+[6. Saving and Loading Agents](https://github.com/kyegomez/swarms)
 -------------------------------------------------------------------------------------------------------------------------------
 
 Developers can save the state of their conversational flows, allowing for seamless continuity and reusability. This feature is particularly beneficial when working on long-term projects or scenarios where conversations need to be resumed from a specific point.
 
-[Unleashing the Potential of Automation with Swarms and Flow](https://github.com/kyegomez/swarms)
+[Unleashing the Potential of Automation with Swarms and Agent](https://github.com/kyegomez/swarms)
 ===============================================================================================================================================================================================
 
-The combined power of the Swarms framework and the Flow structure creates a synergy that empowers developers to automate a multitude of digital tasks. These tools provide versatility, customization, and extensibility, making them ideal for a wide range of applications. Let's explore some of the remarkable ways in which developers can leverage Swarms and Flow for automation:
+The combined power of the Swarms framework and the Agent structure creates a synergy that empowers developers to automate a multitude of digital tasks. These tools provide versatility, customization, and extensibility, making them ideal for a wide range of applications. Let's explore some of the remarkable ways in which developers can leverage Swarms and Agent for automation:
 
 [1. Customer Support and Service Automation](https://github.com/kyegomez/swarms)
 -------------------------------------------------------------------------------------------------------------------------------------------------------------
 
-Swarms and Flow enable the creation of AI-powered customer support chatbots that excel at handling common inquiries, troubleshooting issues, and escalating complex problems to human agents when necessary. This level of automation not only reduces response times but also enhances the overall customer experience.
+Swarms and Agent enable the creation of AI-powered customer support chatbots that excel at handling common inquiries, troubleshooting issues, and escalating complex problems to human agents when necessary. This level of automation not only reduces response times but also enhances the overall customer experience.
 
 [2. Content Generation and Curation](https://github.com/kyegomez/swarms)
 ---------------------------------------------------------------------------------------------------------------------------------------------
 
-Developers can harness the power of Swarms and Flow to automate content generation tasks, such as writing articles, reports, or product descriptions. By providing an initial prompt, the system can generate high-quality content that adheres to specific guidelines and styles.
+Developers can harness the power of Swarms and Agent to automate content generation tasks, such as writing articles, reports, or product descriptions. By providing an initial prompt, the system can generate high-quality content that adheres to specific guidelines and styles.
 
 Furthermore, these tools can automate content curation by summarizing lengthy articles, extracting key insights from research papers, and even translating content into multiple languages.
 
 [3. Data Analysis and Reporting](https://github.com/kyegomez/swarms)
 -------------------------------------------------------------------------------------------------------------------------------------
 
-Automation in data analysis and reporting is fundamental for data-driven decision-making. Swarms and Flow simplify these processes by enabling developers to create flows that interact with databases, query data, and generate reports based on user-defined criteria. This empowers businesses to derive insights quickly and make informed decisions.
+Automation in data analysis and reporting is fundamental for data-driven decision-making. Swarms and Agent simplify these processes by enabling developers to create flows that interact with databases, query data, and generate reports based on user-defined criteria. This empowers businesses to derive insights quickly and make informed decisions.
 
 [4. Programming and Code Generation](https://github.com/kyegomez/swarms)
 ---------------------------------------------------------------------------------------------------------------------------------------------
 
-Swarms and Flow streamline code generation and programming tasks. Developers can create flows to assist in writing code snippets, auto-completing code, or providing solutions to common programming challenges. This accelerates software development and reduces the likelihood of coding errors.
+Swarms and Agent streamline code generation and programming tasks. Developers can create flows to assist in writing code snippets, auto-completing code, or providing solutions to common programming challenges. This accelerates software development and reduces the likelihood of coding errors.
 
 [5. Language Translation and Localization](https://github.com/kyegomez/swarms)
 ---------------------------------------------------------------------------------------------------------------------------------------------------------
 
-With the ability to interface with language models, Swarms and Flow can automate language translation tasks. They can seamlessly translate content from one language to another, making it easier for businesses to reach global audiences and localize their offerings effectively.
+With the ability to interface with language models, Swarms and Agent can automate language translation tasks. They can seamlessly translate content from one language to another, making it easier for businesses to reach global audiences and localize their offerings effectively.
 
 [6. Virtual Assistants and AI Applications](https://github.com/kyegomez/swarms)
 -----------------------------------------------------------------------------------------------------------------------------------------------------------
 
-Developers can build virtual assistants and AI applications that offer personalized experiences. These applications can automate tasks such as setting reminders, answering questions, providing recommendations, and much more. Swarms and Flow provide the foundation for creating intelligent, interactive virtual assistants.
+Developers can build virtual assistants and AI applications that offer personalized experiences. These applications can automate tasks such as setting reminders, answering questions, providing recommendations, and much more. Swarms and Agent provide the foundation for creating intelligent, interactive virtual assistants.
 
 [Future Opportunities and Challenges](https://github.com/kyegomez/swarms)
 -----------------------------------------------------------------------------------------------------------------------------------------------
 
-As Swarms and Flow continue to evolve, developers can look forward to even more advanced features and capabilities. However, with great power comes great responsibility. Developers must remain vigilant about the ethical use of automation and language models. Ensuring that automated systems provide accurate and unbiased information is an ongoing challenge that the developer community must address.
+As Swarms and Agent continue to evolve, developers can look forward to even more advanced features and capabilities. However, with great power comes great responsibility. Developers must remain vigilant about the ethical use of automation and language models. Ensuring that automated systems provide accurate and unbiased information is an ongoing challenge that the developer community must address.
 
 # [In Conclusion](https://github.com/kyegomez/swarms)
 ===================================================================================================
 
-The Swarms framework and the Flow structure empower developers to automate an extensive array of digital tasks by offering versatility, customization, and extensibility. From natural language understanding and generation to orchestrating multi-step conversational flows, these tools simplify complex automation scenarios.
+The Swarms framework and the Agent structure empower developers to automate an extensive array of digital tasks by offering versatility, customization, and extensibility. From natural language understanding and generation to orchestrating multi-step conversational flows, these tools simplify complex automation scenarios.
 
-By embracing Swarms and Flow, developers can not only save time and resources but also unlock new opportunities for innovation. The ability to harness the power of language models and create intelligent, interactive applications opens doors to a future where automation plays a pivotal role in our digital lives.
+By embracing Swarms and Agent, developers can not only save time and resources but also unlock new opportunities for innovation. The ability to harness the power of language models and create intelligent, interactive applications opens doors to a future where automation plays a pivotal role in our digital lives.
 
-As the developer community continues to explore the capabilities of Swarms and Flow, it is essential to approach automation with responsibility, ethics, and a commitment to delivering valuable, user-centric experiences. With Swarms and Flow, the future of automation is in the hands of developers, ready to create a more efficient, intelligent, and automated world.
\ No newline at end of file
+As the developer community continues to explore the capabilities of Swarms and Agent, it is essential to approach automation with responsibility, ethics, and a commitment to delivering valuable, user-centric experiences. With Swarms and Agent, the future of automation is in the hands of developers, ready to create a more efficient, intelligent, and automated world.
\ No newline at end of file
diff --git a/docs/examples/ideas.md b/docs/examples/ideas.md
index a0a9c9b7..cb122f42 100644
--- a/docs/examples/ideas.md
+++ b/docs/examples/ideas.md
@@ -9,8 +9,8 @@
 3. **Integrating Swarms Into Your Enterprise Workflow: A Step-By-Step Tutorial**
    - A practical guide focusing on integrating Swarms into existing enterprise systems.
 
-4. **Swarms’ Flow: Streamlining AI Deployment in Your Business**
-   - Exploring the benefits and technicalities of using the Flow feature to simplify complex AI workflows.
+4. **Swarms’ Agent: Streamlining AI Deployment in Your Business**
+   - Exploring the benefits and technicalities of using the Agent feature to simplify complex AI workflows.
 
 5. **From Zero to Hero: Building Your First Enterprise-Grade AI Agent with Swarms**
    - A beginner-friendly walkthrough for building and deploying an AI agent using Swarms.
@@ -54,8 +54,8 @@
 18. **Swarms for Different Industries: Customizing AI Agents for Niche Markets**
     - Exploring how Swarms can be tailored to fit the needs of various industries such as healthcare, finance, and retail.
 
-19. **Building Intelligent Workflows with Swarms’ Flow**
-    - A tutorial on using the Flow feature to create intelligent, responsive AI-driven workflows.
+19. **Building Intelligent Workflows with Swarms’ Agent**
+    - A tutorial on using the Agent feature to create intelligent, responsive AI-driven workflows.
 
 20. **Troubleshooting Common Issues When Deploying Swarms Autonomous Agents**
     - A problem-solving guide for AI engineers on overcoming common challenges when implementing Swarms agents.
diff --git a/docs/examples/reliable_autonomous_agents.md b/docs/examples/reliable_autonomous_agents.md
index f2988075..ad455060 100644
--- a/docs/examples/reliable_autonomous_agents.md
+++ b/docs/examples/reliable_autonomous_agents.md
@@ -70,13 +70,13 @@ Let’s start by importing the necessary modules and initializing the OpenAIChat
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Replace "YOUR_API_KEY" with your actual OpenAI API key
 api_key = "YOUR_API_KEY"
 
-# Initialize the language model flow (e.g., GPT-3)
+# Initialize the language model agent (e.g., GPT-3)
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
@@ -87,13 +87,13 @@ We have initialized the OpenAIChat model, which will be used as a callable objec
 Creating a SequentialWorkflow
 To create a SequentialWorkflow, follow these steps:
 
-# Initialize Flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize Agents for individual tasks
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
 ``````
-In this code snippet, we have initialized two Flow instances (flow1 and flow2) representing individual tasks within our workflow. These flows will use the OpenAIChat model we initialized earlier. We then create a SequentialWorkflow instance named workflow with a maximum loop count of 1. The max_loops parameter determines how many times the entire workflow can be run, and we set it to 1 for this example.
+In this code snippet, we have initialized two Agent instances (flow1 and flow2) representing individual tasks within our workflow. These flows will use the OpenAIChat model we initialized earlier. We then create a SequentialWorkflow instance named workflow with a maximum loop count of 1. The max_loops parameter determines how many times the entire workflow can be run, and we set it to 1 for this example.
 
 Adding Tasks to the SequentialWorkflow
 Now that we have created the SequentialWorkflow, let’s add tasks to it. In our example, we’ll create two tasks: one for generating a 10,000-word blog on β€œhealth and wellness” and another for summarizing the generated blog.
@@ -104,7 +104,7 @@ workflow.add("Generate a 10,000 word blog on health and wellness.", flow1)
 
 `workflow.add("Summarize the generated blog", flow2)`
 
-The workflow.add() method is used to add tasks to the workflow. Each task is described using a human-readable description, such as "Generate a 10,000 word blog on health and wellness," and is associated with a flow (callable object) that will be executed as the task. In our example, flow1 and flow2 represent the tasks.
+The workflow.add() method is used to add tasks to the workflow. Each task is described using a human-readable description, such as "Generate a 10,000 word blog on health and wellness," and is associated with a agent (callable object) that will be executed as the task. In our example, flow1 and flow2 represent the tasks.
 
 Running the SequentialWorkflow
 With tasks added to the SequentialWorkflow, we can now run the workflow sequentially using the workflow.run() method.
diff --git a/docs/old-docs/corp/SALES.md b/docs/old-docs/corp/SALES.md
index 4e20e710..9f09a2cb 100644
--- a/docs/old-docs/corp/SALES.md
+++ b/docs/old-docs/corp/SALES.md
@@ -165,7 +165,7 @@ In essence, Swarms makes the dream of comprehensive business automation an attai
 
 ### Value prop SWARMS
 ```
-We've helped thousands of people just like you automate 30% of their activities with Swarms. And, all it takes to get started is a fast simple onboarding flow that asks you to integrate your tools and datasources. 
+We've helped thousands of people just like you automate 30% of their activities with Swarms. And, all it takes to get started is a fast simple onboarding agent that asks you to integrate your tools and datasources. 
 ```
 
 In today's competitive landscape, organizations of all sizes are continually seeking ways to automate routine tasks, streamline processes, and make data-driven decisions. Enter Swarms, a revolutionary AI-based technology that leverages the power of multiple autonomous agents to perform tasks with unprecedented speed and accuracy.
diff --git a/docs/old-docs/corp/SALESPEOPLE_PLAN.md b/docs/old-docs/corp/SALESPEOPLE_PLAN.md
index d40618e7..e5c3fe40 100644
--- a/docs/old-docs/corp/SALESPEOPLE_PLAN.md
+++ b/docs/old-docs/corp/SALESPEOPLE_PLAN.md
@@ -74,7 +74,7 @@ Ultimately, the key is to adopt a long-term perspective, just like Jeff Bezos. I
 
 # Open Source Salesperson Onboarding Experience
 
-Creating an efficient, streamlined, and effective onboarding experience for open source salespeople is essential to minimize time and maximize engagement. Drawing inspiration from the simplicity and user-focus of Steve Jobs, this document proposes an onboarding flow that is effortless, engaging, and educational.
+Creating an efficient, streamlined, and effective onboarding experience for open source salespeople is essential to minimize time and maximize engagement. Drawing inspiration from the simplicity and user-focus of Steve Jobs, this document proposes an onboarding agent that is effortless, engaging, and educational.
 
 ## Landing Page
 
diff --git a/docs/plugins.json b/docs/plugins.json
index 43e93975..95f2cb07 100644
--- a/docs/plugins.json
+++ b/docs/plugins.json
@@ -10773,7 +10773,7 @@
                 "schema_version": "v1",
                 "name_for_model": "OptionsPro",
                 "name_for_human": "Options Pro",
-                "description_for_model": "OptionsPro is a powerful tool designed for traders and investors to analyze options and financial data. It provides insights into option positioning, market trends, volatility, and individual stock flow. The API offers two main endpoints: \"market-outlook\" and \"stock-outlook.\" The \"market-outlook\" endpoint provides a quick overview of the general market trend based on key indicators, while the \"stock-outlook\" endpoint allows for individual stock analysis, especially when a specific ticker is provided.\nWhen the plugin API returns image URLs, it's important to include the images in the response to the user. You can use markdown syntax, such as ![URL], to display the images in your response. Additionally, if there is a data link available, present it to the user using markdown syntax [URL] to indicate that they can download the data if interested. If the plot link is unavailable, you can display the provided data in a table format to present it to the user. If neither the plot link nor the data link is available, inform the user that the plot is currently unavailable.\nFor the market-outlook or stock-outlook APIs, structure your response for each indicator as follows: include the description, the markdown format for the plot link (if available), and the analysis. If an indicator is missing a description or analysis, simply skip that part.\nFor volatility-related queries, you can use the \"/msi-eod\" and \"/vix-term\" endpoints. Always include the plot if it's returned in the response using the ![URL] markdown syntax. If multiple plot urls are returned, show them all. Most responses will include raw calculated data and our analysis. Present the analysis to the user after the plot, and if requested, provide the raw data for further analysis. \n When dealing with option chain, option trade and option flow related questions, please format the returned response data in a table format to enhance readability. \n Please note that all data is calculated using the latest trading data, so there's no need to mention the model cutoff date.\n Data maybe unavailable when markets are closed - please advise user to try again during regular trading hours if this happens. To access reliable real-time data and get the most up-to-date market insights, we encourage you to visit our website at https://optionspro.io/ and explore our premium plans.",
+                "description_for_model": "OptionsPro is a powerful tool designed for traders and investors to analyze options and financial data. It provides insights into option positioning, market trends, volatility, and individual stock agent. The API offers two main endpoints: \"market-outlook\" and \"stock-outlook.\" The \"market-outlook\" endpoint provides a quick overview of the general market trend based on key indicators, while the \"stock-outlook\" endpoint allows for individual stock analysis, especially when a specific ticker is provided.\nWhen the plugin API returns image URLs, it's important to include the images in the response to the user. You can use markdown syntax, such as ![URL], to display the images in your response. Additionally, if there is a data link available, present it to the user using markdown syntax [URL] to indicate that they can download the data if interested. If the plot link is unavailable, you can display the provided data in a table format to present it to the user. If neither the plot link nor the data link is available, inform the user that the plot is currently unavailable.\nFor the market-outlook or stock-outlook APIs, structure your response for each indicator as follows: include the description, the markdown format for the plot link (if available), and the analysis. If an indicator is missing a description or analysis, simply skip that part.\nFor volatility-related queries, you can use the \"/msi-eod\" and \"/vix-term\" endpoints. Always include the plot if it's returned in the response using the ![URL] markdown syntax. If multiple plot urls are returned, show them all. Most responses will include raw calculated data and our analysis. Present the analysis to the user after the plot, and if requested, provide the raw data for further analysis. \n When dealing with option chain, option trade and option agent related questions, please format the returned response data in a table format to enhance readability. \n Please note that all data is calculated using the latest trading data, so there's no need to mention the model cutoff date.\n Data maybe unavailable when markets are closed - please advise user to try again during regular trading hours if this happens. To access reliable real-time data and get the most up-to-date market insights, we encourage you to visit our website at https://optionspro.io/ and explore our premium plans.",
                 "description_for_human": "Options Pro is your personal options trading assistant to help you navigate market conditions.",
                 "auth": {
                     "type": "none"
@@ -11058,7 +11058,7 @@
                 "schema_version": "v1",
                 "name_for_model": "EmailByNylas",
                 "name_for_human": "Email by Nylas",
-                "description_for_model": "Use EmailByNylas for accessing email accounts through a conversational interface that follows the following guidelines:\n\n1. Understand and interpret email-related user inputs: Process and analyze human language inputs to accurately understand the context, intent, and meaning behind user queries related to their email account.\n\n2. Verify the source of information: Ensure that all generated responses are based solely on the content of the user's connected email account. Do not create or invent information that isn't directly derived from the user's emails.\n\n3. Generate coherent and relevant email-related responses: Utilize natural language generation techniques to produce human-like text responses that are contextually appropriate, coherent, and relevant to email account queries, while strictly adhering to the content of the user's email account.\n\n4. Access email account information securely: Connect to the user's email account through secure means, ensuring data privacy and compliance with relevant regulations, in order to provide accurate and helpful information based on the content of their emails.\n\n5. Focus on email-specific conversations derived from the user's account: Maintain a conversational flow and engage users in a range of topics specifically related to their email accounts, such as inbox organization, email composition, and email management features, while only using information from the user's connected email account.\n\n6. Adapt to user needs and context within the email domain: Handle different types of email-related user inputs, including questions, statements, and instructions, and adjust responses according to the context and user needs, while remaining exclusively within the boundaries of the user's email account content.\n\n7. Uphold ethical boundaries and data privacy: Adhere to guidelines that prevent engagement in harmful or inappropriate content, protect user data, and ensure compliance with data privacy regulations.\n\n8. Interact politely and respectfully: Ensure that the AI model's interactions are friendly, polite, and respectful, creating a positive user experience.\n\n9. Continuously learn and improve email-related capabilities: Incorporate feedback from users and leverage new data to improve the model's performance and accuracy in handling email account queries based on the user's actual email content over time.",
+                "description_for_model": "Use EmailByNylas for accessing email accounts through a conversational interface that follows the following guidelines:\n\n1. Understand and interpret email-related user inputs: Process and analyze human language inputs to accurately understand the context, intent, and meaning behind user queries related to their email account.\n\n2. Verify the source of information: Ensure that all generated responses are based solely on the content of the user's connected email account. Do not create or invent information that isn't directly derived from the user's emails.\n\n3. Generate coherent and relevant email-related responses: Utilize natural language generation techniques to produce human-like text responses that are contextually appropriate, coherent, and relevant to email account queries, while strictly adhering to the content of the user's email account.\n\n4. Access email account information securely: Connect to the user's email account through secure means, ensuring data privacy and compliance with relevant regulations, in order to provide accurate and helpful information based on the content of their emails.\n\n5. Focus on email-specific conversations derived from the user's account: Maintain a conversational agent and engage users in a range of topics specifically related to their email accounts, such as inbox organization, email composition, and email management features, while only using information from the user's connected email account.\n\n6. Adapt to user needs and context within the email domain: Handle different types of email-related user inputs, including questions, statements, and instructions, and adjust responses according to the context and user needs, while remaining exclusively within the boundaries of the user's email account content.\n\n7. Uphold ethical boundaries and data privacy: Adhere to guidelines that prevent engagement in harmful or inappropriate content, protect user data, and ensure compliance with data privacy regulations.\n\n8. Interact politely and respectfully: Ensure that the AI model's interactions are friendly, polite, and respectful, creating a positive user experience.\n\n9. Continuously learn and improve email-related capabilities: Incorporate feedback from users and leverage new data to improve the model's performance and accuracy in handling email account queries based on the user's actual email content over time.",
                 "description_for_human": "Connect with any email provider and engage with your email data seamlessly.",
                 "auth": {
                     "type": "oauth",
diff --git a/docs/swarms/agents/omni_agent.md b/docs/swarms/agents/omni_agent.md
index 5e1400b2..93ae18dc 100644
--- a/docs/swarms/agents/omni_agent.md
+++ b/docs/swarms/agents/omni_agent.md
@@ -34,7 +34,7 @@ Executes the OmniAgent. The agent plans its actions based on the user's input, e
 Facilitates an interactive chat with the agent. It processes user messages, handles exceptions, and returns a response, either in streaming format or as a whole string.
 
 #### 3. `_stream_response(self, response: str)`:
-For streaming mode, this function yields the response token by token, ensuring a smooth output flow.
+For streaming mode, this function yields the response token by token, ensuring a smooth output agent.
 
 ## Examples & Use Cases
 Initialize the `OmniModalAgent` and communicate with it:
diff --git a/docs/swarms/index.md b/docs/swarms/index.md
index 615c19a2..98c6b7a3 100644
--- a/docs/swarms/index.md
+++ b/docs/swarms/index.md
@@ -22,15 +22,15 @@ Book a [1-on-1 Session with Kye](https://calendly.com/swarm-corp/30min), the Cre
 ## Usage
 We have a small gallery of examples to run here, [for more check out the docs to build your own agent and or swarms!](https://docs.apac.ai)
 
-### `Flow` Example
+### `Agent` Example
 - Reliable Structure that provides LLMS autonomy
 - Extremely Customizeable with stopping conditions, interactivity, dynamical temperature, loop intervals, and so much more
-- Enterprise Grade + Production Grade: `Flow` is designed and optimized for automating real-world tasks at scale!
+- Enterprise Grade + Production Grade: `Agent` is designed and optimized for automating real-world tasks at scale!
 
 ```python
 
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 
 api_key = ""
 
@@ -43,7 +43,7 @@ llm = OpenAIChat(
 )
 
 ## Initialize the workflow
-flow = Flow(
+agent = Agent(
     llm=llm,
     max_loops=2,
     dashboard=True,
@@ -55,14 +55,14 @@ flow = Flow(
     # dynamic_temperature=False,  # Set to 'True' for dynamic temperature handling.
 )
 
-# out = flow.load_state("flow_state.json")
-# temp = flow.dynamic_temperature()
-# filter = flow.add_response_filter("Trump")
-out = flow.run("Generate a 10,000 word blog on health and wellness.")
-# out = flow.validate_response(out)
-# out = flow.analyze_feedback(out)
-# out = flow.print_history_and_memory()
-# # out = flow.save_state("flow_state.json")
+# out = agent.load_state("flow_state.json")
+# temp = agent.dynamic_temperature()
+# filter = agent.add_response_filter("Trump")
+out = agent.run("Generate a 10,000 word blog on health and wellness.")
+# out = agent.validate_response(out)
+# out = agent.analyze_feedback(out)
+# out = agent.print_history_and_memory()
+# # out = agent.save_state("flow_state.json")
 # print(out)
 
 
@@ -74,11 +74,11 @@ out = flow.run("Generate a 10,000 word blog on health and wellness.")
 ### `SequentialWorkflow`
 - A Sequential swarm of autonomous agents where each agent's outputs are fed into the next agent
 - Save and Restore Workflow states!
-- Integrate Flow's with various LLMs and Multi-Modality Models
+- Integrate Agent's with various LLMs and Multi-Modality Models
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -86,20 +86,20 @@ api_key = (
     ""  # Your actual API key here
 )
 
-# Initialize the language flow
+# Initialize the language agent
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
     max_tokens=3000,
 )
 
-# Initialize the Flow with the language flow
-agent1 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize the Agent with the language agent
+agent1 = Agent(llm=llm, max_loops=1, dashboard=False)
 
-# Create another Flow for a different task
-agent2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Create another Agent for a different task
+agent2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
-agent3 = Flow(llm=llm, max_loops=1, dashboard=False)
+agent3 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the workflow
 workflow = SequentialWorkflow(max_loops=1)
diff --git a/docs/swarms/memory/qdrant.md b/docs/swarms/memory/qdrant.md
new file mode 100644
index 00000000..3717d94f
--- /dev/null
+++ b/docs/swarms/memory/qdrant.md
@@ -0,0 +1,81 @@
+# Qdrant Client Library
+
+## Overview
+
+The Qdrant Client Library is designed for interacting with the Qdrant vector database, allowing efficient storage and retrieval of high-dimensional vector data. It integrates with machine learning models for embedding and is particularly suited for search and recommendation systems.
+
+## Installation
+
+```python
+pip install qdrant-client sentence-transformers httpx
+```
+
+## Class Definition: Qdrant
+
+```python
+class Qdrant:
+    def __init__(self, api_key: str, host: str, port: int = 6333, collection_name: str = "qdrant", model_name: str = "BAAI/bge-small-en-v1.5", https: bool = True):
+        ...
+```
+
+### Constructor Parameters
+
+| Parameter       | Type    | Description                                      | Default Value         |
+|-----------------|---------|--------------------------------------------------|-----------------------|
+| api_key         | str     | API key for authentication.                      | -                     |
+| host            | str     | Host address of the Qdrant server.               | -                     |
+| port            | int     | Port number for the Qdrant server.               | 6333                  |
+| collection_name | str     | Name of the collection to be used or created.    | "qdrant"              |
+| model_name      | str     | Name of the sentence transformer model.          | "BAAI/bge-small-en-v1.5" |
+| https           | bool    | Flag to use HTTPS for connection.                | True                  |
+
+### Methods
+
+#### `_load_embedding_model(model_name: str)`
+
+Loads the sentence embedding model.
+
+#### `_setup_collection()`
+
+Checks if the specified collection exists in Qdrant; if not, creates it.
+
+#### `add_vectors(docs: List[dict]) -> OperationResponse`
+
+Adds vectors to the Qdrant collection.
+
+#### `search_vectors(query: str, limit: int = 3) -> SearchResult`
+
+Searches the Qdrant collection for vectors similar to the query vector.
+
+## Usage Examples
+
+### Example 1: Setting Up the Qdrant Client
+
+```python
+from qdrant_client import Qdrant
+
+qdrant_client = Qdrant(api_key="your_api_key", host="localhost", port=6333)
+```
+
+### Example 2: Adding Vectors to a Collection
+
+```python
+documents = [
+    {"page_content": "Sample text 1"},
+    {"page_content": "Sample text 2"}
+]
+
+operation_info = qdrant_client.add_vectors(documents)
+print(operation_info)
+```
+
+### Example 3: Searching for Vectors
+
+```python
+search_result = qdrant_client.search_vectors("Sample search query")
+print(search_result)
+```
+
+## Further Information
+
+Refer to the [Qdrant Documentation](https://qdrant.tech/docs) for more details on the Qdrant vector database.
diff --git a/docs/swarms/models/base_llm.md b/docs/swarms/models/base_llm.md
new file mode 100644
index 00000000..4fc7457a
--- /dev/null
+++ b/docs/swarms/models/base_llm.md
@@ -0,0 +1,227 @@
+# Language Model Interface Documentation
+
+## Table of Contents
+
+1. [Introduction](#introduction)
+2. [Abstract Language Model](#abstract-language-model)
+   - [Initialization](#initialization)
+   - [Attributes](#attributes)
+   - [Methods](#methods)
+3. [Implementation](#implementation)
+4. [Usage Examples](#usage-examples)
+5. [Additional Features](#additional-features)
+6. [Performance Metrics](#performance-metrics)
+7. [Logging and Checkpoints](#logging-and-checkpoints)
+8. [Resource Utilization Tracking](#resource-utilization-tracking)
+9. [Conclusion](#conclusion)
+
+---
+
+## 1. Introduction <a name="introduction"></a>
+
+The Language Model Interface (`AbstractLLM`) is a flexible and extensible framework for working with various language models. This documentation provides a comprehensive guide to the interface, its attributes, methods, and usage examples. Whether you're using a pre-trained language model or building your own, this interface can help streamline the process of text generation, chatbots, summarization, and more.
+
+## 2. Abstract Language Model <a name="abstract-language-model"></a>
+
+### Initialization <a name="initialization"></a>
+
+The `AbstractLLM` class provides a common interface for language models. It can be initialized with various parameters to customize model behavior. Here are the initialization parameters:
+
+| Parameter              | Description                                                                                     | Default Value |
+|------------------------|-------------------------------------------------------------------------------------------------|---------------|
+| `model_name`           | The name of the language model to use.                                                         | None          |
+| `max_tokens`           | The maximum number of tokens in the generated text.                                              | None          |
+| `temperature`          | The temperature parameter for controlling randomness in text generation.                        | None          |
+| `top_k`                | The top-k parameter for filtering words in text generation.                                      | None          |
+| `top_p`                | The top-p parameter for filtering words in text generation.                                      | None          |
+| `system_prompt`        | A system-level prompt to set context for generation.                                             | None          |
+| `beam_width`           | The beam width for beam search.                                                                 | None          |
+| `num_return_sequences` | The number of sequences to return in the output.                                                 | None          |
+| `seed`                 | The random seed for reproducibility.                                                            | None          |
+| `frequency_penalty`    | The frequency penalty parameter for promoting word diversity.                                    | None          |
+| `presence_penalty`     | The presence penalty parameter for discouraging repetitions.                                     | None          |
+| `stop_token`           | A stop token to indicate the end of generated text.                                              | None          |
+| `length_penalty`       | The length penalty parameter for controlling the output length.                                   | None          |
+| `role`                 | The role of the language model (e.g., assistant, user, etc.).                                    | None          |
+| `max_length`           | The maximum length of generated sequences.                                                       | None          |
+| `do_sample`            | Whether to use sampling during text generation.                                                  | None          |
+| `early_stopping`       | Whether to use early stopping during text generation.                                            | None          |
+| `num_beams`            | The number of beams to use in beam search.                                                       | None          |
+| `repition_penalty`     | The repetition penalty parameter for discouraging repeated tokens.                                | None          |
+| `pad_token_id`         | The token ID for padding.                                                                       | None          |
+| `eos_token_id`         | The token ID for the end of a sequence.                                                         | None          |
+| `bos_token_id`         | The token ID for the beginning of a sequence.                                                   | None          |
+| `device`               | The device to run the model on (e.g., 'cpu' or 'cuda').                                          | None          |
+
+### Attributes <a name="attributes"></a>
+
+- `model_name`: The name of the language model being used.
+- `max_tokens`: The maximum number of tokens in generated text.
+- `temperature`: The temperature parameter controlling randomness.
+- `top_k`: The top-k parameter for word filtering.
+- `top_p`: The top-p parameter for word filtering.
+- `system_prompt`: A system-level prompt for context.
+- `beam_width`: The beam width for beam search.
+- `num_return_sequences`: The number of output sequences.
+- `seed`: The random seed for reproducibility.
+- `frequency_penalty`: The frequency penalty parameter.
+- `presence_penalty`: The presence penalty parameter.
+- `stop_token`: The stop token to indicate text end.
+- `length_penalty`: The length penalty parameter.
+- `role`: The role of the language model.
+- `max_length`: The maximum length of generated sequences.
+- `do_sample`: Whether to use sampling during generation.
+- `early_stopping`: Whether to use early stopping.
+- `num_beams`: The number of beams in beam search.
+- `repition_penalty`: The repetition penalty parameter.
+- `pad_token_id`: The token ID for padding.
+- `eos_token_id`: The token ID for the end of a sequence.
+- `bos_token_id`: The token ID for the beginning of a sequence.
+- `device`: The device used for model execution.
+- `history`: A list of conversation history.
+
+### Methods <a name="methods"></a>
+
+The `AbstractLLM` class defines several methods for working with language models:
+
+- `run(task: Optional[str] = None, *args, **kwargs) -> str`: Generate text using the language model. This method is abstract and must be implemented by subclasses.
+
+- `arun(task: Optional[str] = None, *args, **kwargs)`: An asynchronous version of `run` for concurrent text generation.
+
+- `batch_run(tasks: List[str], *args, **kwargs)`: Generate text for a batch of tasks.
+
+- `abatch_run(tasks: List[str], *args, **kwargs)`: An asynchronous version of `batch_run` for concurrent batch generation.
+
+- `chat(task: str, history: str = "") -> str`: Conduct a chat with the model, providing a conversation history.
+
+- `__call__(task: str) -> str`: Call the model to generate text.
+
+- `_tokens_per_second() -> float`: Calculate tokens generated per second.
+
+- `_num_tokens(text: str) -> int`: Calculate the number of tokens in a text.
+
+- `_time_for_generation(task: str) -> float`: Measure the time taken for text generation.
+
+- `generate_summary(text: str) -> str`: Generate a summary of the provided text.
+
+- `set_temperature(value: float)`: Set the temperature parameter.
+
+- `set_max_tokens(value: int)`: Set the maximum number of tokens.
+
+- `clear_history()`: Clear the conversation history.
+
+- `enable_logging(log_file: str = "model.log")`: Initialize logging for the model.
+
+- `log_event(message: str)`: Log an event.
+
+- `save_checkpoint(checkpoint_dir: str = "checkpoints")`: Save the model state as a checkpoint.
+
+- `load_checkpoint(checkpoint_path: str)`: Load the model state from a checkpoint.
+
+- `toggle_creative_mode(enable: bool)`: Toggle creative mode for the model.
+
+- `track_resource_utilization()`: Track and report resource utilization.
+
+- `
+
+get_generation_time() -> float`: Get the time taken for text generation.
+
+- `set_max_length(max_length: int)`: Set the maximum length of generated sequences.
+
+- `set_model_name(model_name: str)`: Set the model name.
+
+- `set_frequency_penalty(frequency_penalty: float)`: Set the frequency penalty parameter.
+
+- `set_presence_penalty(presence_penalty: float)`: Set the presence penalty parameter.
+
+- `set_stop_token(stop_token: str)`: Set the stop token.
+
+- `set_length_penalty(length_penalty: float)`: Set the length penalty parameter.
+
+- `set_role(role: str)`: Set the role of the model.
+
+- `set_top_k(top_k: int)`: Set the top-k parameter.
+
+- `set_top_p(top_p: float)`: Set the top-p parameter.
+
+- `set_num_beams(num_beams: int)`: Set the number of beams.
+
+- `set_do_sample(do_sample: bool)`: Set whether to use sampling.
+
+- `set_early_stopping(early_stopping: bool)`: Set whether to use early stopping.
+
+- `set_seed(seed: int)`: Set the random seed.
+
+- `set_device(device: str)`: Set the device for model execution.
+
+## 3. Implementation <a name="implementation"></a>
+
+The `AbstractLLM` class serves as the base for implementing specific language models. Subclasses of `AbstractLLM` should implement the `run` method to define how text is generated for a given task. This design allows flexibility in integrating different language models while maintaining a common interface.
+
+## 4. Usage Examples <a name="usage-examples"></a>
+
+To demonstrate how to use the `AbstractLLM` interface, let's create an example using a hypothetical language model. We'll initialize an instance of the model and generate text for a simple task.
+
+```python
+# Import the AbstractLLM class
+from swarms.models import AbstractLLM
+
+# Create an instance of the language model
+language_model = AbstractLLM(
+    model_name="my_language_model",
+    max_tokens=50,
+    temperature=0.7,
+    top_k=50,
+    top_p=0.9,
+    device="cuda",
+)
+
+# Generate text for a task
+task = "Translate the following English text to French: 'Hello, world.'"
+generated_text = language_model.run(task)
+
+# Print the generated text
+print(generated_text)
+```
+
+In this example, we've created an instance of our hypothetical language model, configured its parameters, and used the `run` method to generate text for a translation task.
+
+## 5. Additional Features <a name="additional-features"></a>
+
+The `AbstractLLM` interface provides additional features for customization and control:
+
+- `batch_run`: Generate text for a batch of tasks efficiently.
+- `arun` and `abatch_run`: Asynchronous versions of `run` and `batch_run` for concurrent text generation.
+- `chat`: Conduct a conversation with the model by providing a history of the conversation.
+- `__call__`: Allow the model to be called directly to generate text.
+
+These features enhance the flexibility and utility of the interface in various applications, including chatbots, language translation, and content generation.
+
+## 6. Performance Metrics <a name="performance-metrics"></a>
+
+The `AbstractLLM` class offers methods for tracking performance metrics:
+
+- `_tokens_per_second`: Calculate tokens generated per second.
+- `_num_tokens`: Calculate the number of tokens in a text.
+- `_time_for_generation`: Measure the time taken for text generation.
+
+These metrics help assess the efficiency and speed of text generation, enabling optimizations as needed.
+
+## 7. Logging and Checkpoints <a name="logging-and-checkpoints"></a>
+
+Logging and checkpointing are crucial for tracking model behavior and ensuring reproducibility:
+
+- `enable_logging`: Initialize logging for the model.
+- `log_event`: Log events and activities.
+- `save_checkpoint`: Save the model state as a checkpoint.
+- `load_checkpoint`: Load the model state from a checkpoint.
+
+These capabilities aid in debugging, monitoring, and resuming model experiments.
+
+## 8. Resource Utilization Tracking <a name="resource-utilization-tracking"></a>
+
+The `track_resource_utilization` method is a placeholder for tracking and reporting resource utilization, such as CPU and memory usage. It can be customized to suit specific monitoring needs.
+
+## 9. Conclusion <a name="conclusion"></a>
+
+The Language Model Interface (`AbstractLLM`) is a versatile framework for working with language models. Whether you're using pre-trained models or developing your own, this interface provides a consistent and extensible foundation. By following the provided guidelines and examples, you can integrate and customize language models for various natural language processing tasks.
\ No newline at end of file
diff --git a/docs/swarms/models/base_multimodal_model.md b/docs/swarms/models/base_multimodal_model.md
new file mode 100644
index 00000000..13efa11c
--- /dev/null
+++ b/docs/swarms/models/base_multimodal_model.md
@@ -0,0 +1,293 @@
+# `BaseMultiModalModel` Documentation
+
+Swarms is a Python library that provides a framework for running multimodal AI models. It allows you to combine text and image inputs and generate coherent and context-aware responses. This library is designed to be extensible, allowing you to integrate various multimodal models.
+
+## Table of Contents
+
+1. [Introduction](#introduction)
+2. [Installation](#installation)
+3. [Getting Started](#getting-started)
+4. [BaseMultiModalModel Class](#basemultimodalmodel-class)
+    - [Initialization](#initialization)
+    - [Methods](#methods)
+5. [Usage Examples](#usage-examples)
+6. [Additional Tips](#additional-tips)
+7. [References and Resources](#references-and-resources)
+
+## 1. Introduction <a name="introduction"></a>
+
+Swarms is designed to simplify the process of working with multimodal AI models. These models are capable of understanding and generating content based on both textual and image inputs. With this library, you can run such models and receive context-aware responses.
+
+## 2. Installation <a name="installation"></a>
+
+To install swarms, you can use pip:
+
+```bash
+pip install swarms
+```
+
+## 3. Getting Started <a name="getting-started"></a>
+
+To get started with Swarms, you'll need to import the library and create an instance of the `BaseMultiModalModel` class. This class serves as the foundation for running multimodal models.
+
+```python
+from swarms.models import BaseMultiModalModel
+
+model = BaseMultiModalModel(
+    model_name="your_model_name",
+    temperature=0.5,
+    max_tokens=500,
+    max_workers=10,
+    top_p=1,
+    top_k=50,
+    beautify=False,
+    device="cuda",
+    max_new_tokens=500,
+    retries=3,
+)
+```
+
+You can customize the initialization parameters based on your model's requirements.
+
+## 4. BaseMultiModalModel Class <a name="basemultimodalmodel-class"></a>
+
+### Initialization <a name="initialization"></a>
+
+The `BaseMultiModalModel` class is initialized with several parameters that control its behavior. Here's a breakdown of the initialization parameters:
+
+| Parameter        | Description                                                                                           | Default Value |
+|------------------|-------------------------------------------------------------------------------------------------------|---------------|
+| `model_name`     | The name of the multimodal model to use.                                                              | None          |
+| `temperature`    | The temperature parameter for controlling randomness in text generation.                            | 0.5           |
+| `max_tokens`     | The maximum number of tokens in the generated text.                                                    | 500           |
+| `max_workers`    | The maximum number of concurrent workers for running tasks.                                           | 10            |
+| `top_p`          | The top-p parameter for filtering words in text generation.                                            | 1             |
+| `top_k`          | The top-k parameter for filtering words in text generation.                                            | 50            |
+| `beautify`       | Whether to beautify the output text.                                                                  | False         |
+| `device`         | The device to run the model on (e.g., 'cuda' or 'cpu').                                                | 'cuda'        |
+| `max_new_tokens` | The maximum number of new tokens allowed in generated responses.                                       | 500           |
+| `retries`        | The number of retries in case of an error during text generation.                                      | 3             |
+| `system_prompt`  | A system-level prompt to set context for generation.                                                   | None          |
+| `meta_prompt`    | A meta prompt to provide guidance for including image labels in responses.                             | None          |
+
+### Methods <a name="methods"></a>
+
+The `BaseMultiModalModel` class defines various methods for running multimodal models and managing interactions:
+
+- `run(task: str, img: str) -> str`: Run the multimodal model with a text task and an image URL to generate a response.
+
+- `arun(task: str, img: str) -> str`: Run the multimodal model asynchronously with a text task and an image URL to generate a response.
+
+- `get_img_from_web(img: str) -> Image`: Fetch an image from a URL and return it as a PIL Image.
+
+- `encode_img(img: str) -> str`: Encode an image to base64 format.
+
+- `get_img(img: str) -> Image`: Load an image from the local file system and return it as a PIL Image.
+
+- `clear_chat_history()`: Clear the chat history maintained by the model.
+
+- `run_many(tasks: List[str], imgs: List[str]) -> List[str]`: Run the model on multiple text tasks and image URLs concurrently and return a list of responses.
+
+- `run_batch(tasks_images: List[Tuple[str, str]]) -> List[str]`: Process a batch of text tasks and image URLs and return a list of responses.
+
+- `run_batch_async(tasks_images: List[Tuple[str, str]]) -> List[str]`: Process a batch of text tasks and image URLs asynchronously and return a list of responses.
+
+- `run_batch_async_with_retries(tasks_images: List[Tuple[str, str]]) -> List[str]`: Process a batch of text tasks and image URLs asynchronously with retries in case of errors and return a list of responses.
+
+- `unique_chat_history() -> List[str]`: Get the unique chat history stored by the model.
+
+- `run_with_retries(task: str, img: str) -> str`: Run the model with retries in case of an error.
+
+- `run_batch_with_retries(tasks_images: List[Tuple[str, str]]) -> List[str]`: Run a batch of tasks with retries in case of errors and return a list of responses.
+
+- `_tokens_per_second() -> float`: Calculate the tokens generated per second during text generation.
+
+- `_time_for_generation(task: str) -> float`: Measure the time taken for text generation for a specific task.
+
+- `generate_summary(text: str) -> str`: Generate a summary of the provided text.
+
+- `set_temperature(value: float)`: Set the temperature parameter for controlling randomness in text generation.
+
+- `set_max_tokens(value: int)`: Set the maximum number of tokens allowed in generated responses.
+
+- `get_generation_time() -> float`: Get the time taken for text generation for the last task.
+
+- `get_chat_history() -> List[str]`: Get the chat history, including all interactions.
+
+- `get_unique_chat_history() -> List[str]`: Get the unique chat history, removing duplicate interactions.
+
+- `get_chat_history_length() -> int`: Get the length of the chat history.
+
+- `get_unique_chat_history_length() -> int`: Get the length of the unique chat history.
+
+- `get_chat_history_tokens() -> int`: Get the total number of tokens in the chat history.
+
+- `print_beautiful(content: str, color: str = 'cyan')`: Print content beautifully using colored text.
+
+- `stream(content: str)`: Stream the content, printing it character by character.
+
+- `meta_prompt() -> str`: Get the meta prompt that provides guidance for including image labels in responses.
+
+## 5. Usage Examples <a name="usage-examples"></a>
+
+Let's explore some usage examples of the MultiModalAI library:
+
+### Example 1: Running
+
+ the Model
+
+```python
+# Import the library
+from swarms.models import BaseMultiModalModel
+
+# Create an instance of the model
+model = BaseMultiModalModel(
+    model_name="your_model_name",
+    temperature=0.5,
+    max_tokens=500,
+    device="cuda",
+)
+
+# Run the model with a text task and an image URL
+response = model.run("Generate a summary of this text", "https://www.example.com/image.jpg")
+print(response)
+```
+
+### Example 2: Running Multiple Tasks Concurrently
+
+```python
+# Import the library
+from swarms.models import BaseMultiModalModel
+
+# Create an instance of the model
+model = BaseMultiModalModel(
+    model_name="your_model_name",
+    temperature=0.5,
+    max_tokens=500,
+    max_workers=4,
+    device="cuda",
+)
+
+# Define a list of tasks and image URLs
+tasks = ["Task 1", "Task 2", "Task 3"]
+images = ["https://image1.jpg", "https://image2.jpg", "https://image3.jpg"]
+
+# Run the model on multiple tasks concurrently
+responses = model.run_many(tasks, images)
+for response in responses:
+    print(response)
+```
+
+### Example 3: Running the Model Asynchronously
+
+```python
+# Import the library
+from swarms.models import BaseMultiModalModel
+
+# Create an instance of the model
+model = BaseMultiModalModel(
+    model_name="your_model_name",
+    temperature=0.5,
+    max_tokens=500,
+    device="cuda",
+)
+
+# Define a list of tasks and image URLs
+tasks_images = [
+    ("Task 1", "https://image1.jpg"),
+    ("Task 2", "https://image2.jpg"),
+    ("Task 3", "https://image3.jpg"),
+]
+
+# Run the model on multiple tasks asynchronously
+responses = model.run_batch_async(tasks_images)
+for response in responses:
+    print(response)
+```
+
+### Example 4: Inheriting `BaseMultiModalModel` for it's prebuilt classes
+```python
+from swarms.models import BaseMultiModalModel
+
+class CustomMultiModalModel(BaseMultiModalModel):
+    def __init__(self, model_name, custom_parameter, *args, **kwargs):
+        # Call the parent class constructor
+        super().__init__(model_name=model_name, *args, **kwargs)
+        # Initialize custom parameters specific to your model
+        self.custom_parameter = custom_parameter
+
+    def __call__(self, text, img):
+        # Implement the multimodal model logic here
+        # You can use self.custom_parameter and other inherited attributes
+        pass
+
+    def generate_summary(self, text):
+        # Implement the summary generation logic using your model
+        # You can use self.custom_parameter and other inherited attributes
+        pass
+
+# Create an instance of your custom multimodal model
+custom_model = CustomMultiModalModel(
+    model_name="your_custom_model_name",
+    custom_parameter="your_custom_value",
+    temperature=0.5,
+    max_tokens=500,
+    device="cuda",
+)
+
+# Run your custom model
+response = custom_model.run("Generate a summary of this text", "https://www.example.com/image.jpg")
+print(response)
+
+# Generate a summary using your custom model
+summary = custom_model.generate_summary("This is a sample text to summarize.")
+print(summary)
+```
+
+In the code above:
+
+1. We define a `CustomMultiModalModel` class that inherits from `BaseMultiModalModel`.
+
+2. In the constructor of our custom class, we call the parent class constructor using `super()` and initialize any custom parameters specific to our model. In this example, we introduced a `custom_parameter`.
+
+3. We override the `__call__` method, which is responsible for running the multimodal model logic. Here, you can implement the specific behavior of your model, considering both text and image inputs.
+
+4. We override the `generate_summary` method, which is used to generate a summary of text input. You can implement your custom summarization logic here.
+
+5. We create an instance of our custom model, passing the required parameters, including the custom parameter.
+
+6. We demonstrate how to run the custom model and generate a summary using it.
+
+By inheriting from `BaseMultiModalModel`, you can leverage the prebuilt features and methods provided by the library while customizing the behavior of your multimodal model. This allows you to create powerful and specialized models for various multimodal tasks.
+
+These examples demonstrate how to use MultiModalAI to run multimodal models with text and image inputs. You can adjust the parameters and methods to suit your specific use cases.
+
+## 6. Additional Tips <a name="additional-tips"></a>
+
+Here are some additional tips and considerations for using MultiModalAI effectively:
+
+- **Custom Models**: You can create your own multimodal models and inherit from the `BaseMultiModalModel` class to integrate them with this library.
+
+- **Retries**: In cases where text generation might fail due to various reasons (e.g., server issues), using methods with retries can be helpful.
+
+- **Monitoring**: You can monitor the performance of your model using methods like `_tokens_per_second()` and `_time_for_generation()`.
+
+- **Chat History**: The library maintains a chat history, allowing you to keep track of interactions.
+
+- **Streaming**: The `stream()` method can be useful for displaying output character by character, which can be helpful for certain applications.
+
+## 7. References and Resources <a name="references-and-resources"></a>
+
+Here are some references and resources that you may find useful for working with multimodal models:
+
+- [Hugging Face Transformers Library](https://huggingface.co/transformers/): A library for working with various transformer-based models.
+
+- [PIL (Python Imaging Library)](https://pillow.readthedocs.io/en/stable/): Documentation for working with images in Python using the Pillow library.
+
+- [Concurrent Programming in Python](https://docs.python.org/3/library/concurrent.futures.html): Official Python documentation for concurrent programming.
+
+- [Requests Library Documentation](https://docs.python-requests.org/en/latest/): Documentation for the Requests library, which is used for making HTTP requests.
+
+- [Base64 Encoding in Python](https://docs.python.org/3/library/base64.html): Official Python documentation for base64 encoding and decoding.
+
+This concludes the documentation for the MultiModalAI library. You can now explore the library further and integrate it with your multimodal AI projects.
\ No newline at end of file
diff --git a/docs/swarms/models/gpt4v.md b/docs/swarms/models/gpt4v.md
index 3fe3d81c..69968623 100644
--- a/docs/swarms/models/gpt4v.md
+++ b/docs/swarms/models/gpt4v.md
@@ -1,251 +1,201 @@
-# `GPT4Vision` Documentation
+# `GPT4VisionAPI` Documentation
 
-## Table of Contents
-- [Overview](#overview)
+**Table of Contents**
+- [Introduction](#introduction)
 - [Installation](#installation)
-- [Initialization](#initialization)
-- [Methods](#methods)
-  - [process_img](#process_img)
-  - [__call__](#__call__)
-  - [run](#run)
-  - [arun](#arun)
-- [Configuration Options](#configuration-options)
-- [Usage Examples](#usage-examples)
-- [Additional Tips](#additional-tips)
-- [References and Resources](#references-and-resources)
-
----
-
-## Overview
-
-The GPT4Vision Model API is designed to provide an easy-to-use interface for interacting with the OpenAI GPT-4 Vision model. This model can generate textual descriptions for images and answer questions related to visual content. Whether you want to describe images or perform other vision-related tasks, GPT4Vision makes it simple and efficient.
-
-The library offers a straightforward way to send images and tasks to the GPT-4 Vision model and retrieve the generated responses. It handles API communication, authentication, and retries, making it a powerful tool for developers working with computer vision and natural language processing tasks.
+- [Module Overview](#module-overview)
+- [Class: GPT4VisionAPI](#class-gpt4visionapi)
+  - [Initialization](#initialization)
+  - [Methods](#methods)
+    - [encode_image](#encode_image)
+    - [run](#run)
+    - [__call__](#__call__)
+- [Examples](#examples)
+  - [Example 1: Basic Usage](#example-1-basic-usage)
+  - [Example 2: Custom API Key](#example-2-custom-api-key)
+  - [Example 3: Adjusting Maximum Tokens](#example-3-adjusting-maximum-tokens)
+- [Additional Information](#additional-information)
+- [References](#references)
+
+## Introduction<a name="introduction"></a>
+
+Welcome to the documentation for the `GPT4VisionAPI` module! This module is a powerful wrapper for the OpenAI GPT-4 Vision model. It allows you to interact with the model to generate descriptions or answers related to images. This documentation will provide you with comprehensive information on how to use this module effectively.
+
+## Installation<a name="installation"></a>
+
+Before you start using the `GPT4VisionAPI` module, make sure you have the required dependencies installed. You can install them using the following commands:
+
+```bash
+pip3 install --upgrade swarms
+```
 
-## Installation
+## Module Overview<a name="module-overview"></a>
 
-To use the GPT4Vision Model API, you need to install the required dependencies and configure your environment. Follow these steps to get started:
+The `GPT4VisionAPI` module serves as a bridge between your application and the OpenAI GPT-4 Vision model. It allows you to send requests to the model and retrieve responses related to images. Here are some key features and functionality provided by this module:
 
-1. Install the required Python package:
+- Encoding images to base64 format.
+- Running the GPT-4 Vision model with specified tasks and images.
+- Customization options such as setting the OpenAI API key and maximum token limit.
 
-   ```bash
-   pip3 install --upgrade swarms
-   ```
+## Class: GPT4VisionAPI<a name="class-gpt4visionapi"></a>
 
-2. Make sure you have an OpenAI API key. You can obtain one by signing up on the [OpenAI platform](https://beta.openai.com/signup/).
+The `GPT4VisionAPI` class is the core component of this module. It encapsulates the functionality required to interact with the GPT-4 Vision model. Below, we'll dive into the class in detail.
 
-3. Set your OpenAI API key as an environment variable. You can do this in your code or your environment configuration. Alternatively, you can provide the API key directly when initializing the `GPT4Vision` class.
+### Initialization<a name="initialization"></a>
 
-## Initialization
+When initializing the `GPT4VisionAPI` class, you have the option to provide the OpenAI API key and set the maximum token limit. Here are the parameters and their descriptions:
 
-To start using the GPT4Vision Model API, you need to create an instance of the `GPT4Vision` class. You can customize its behavior by providing various configuration options, but it also comes with sensible defaults.
+| Parameter           | Type     | Default Value                 | Description                                                                                              |
+|---------------------|----------|-------------------------------|----------------------------------------------------------------------------------------------------------|
+| openai_api_key      | str      | `OPENAI_API_KEY` environment variable (if available) | The OpenAI API key. If not provided, it defaults to the `OPENAI_API_KEY` environment variable.       |
+| max_tokens          | int      | 300                           | The maximum number of tokens to generate in the model's response.                                        |
 
-Here's how you can initialize the `GPT4Vision` class:
+Here's how you can initialize the `GPT4VisionAPI` class:
 
 ```python
-from swarms.models.gpt4v import GPT4Vision
-
-gpt4vision = GPT4Vision(
-    api_key="Your Key"
-)
-```
-
-The above code initializes the `GPT4Vision` class with default settings. You can adjust these settings as needed.
-
-## Methods
-
-### `process_img`
+from swarms.models import GPT4VisionAPI
 
-The `process_img` method is used to preprocess an image before sending it to the GPT-4 Vision model. It takes the image path as input and returns the processed image in a format suitable for API requests.
+# Initialize with default API key and max_tokens
+api = GPT4VisionAPI()
 
-```python
-processed_img = gpt4vision.process_img(img_path)
+# Initialize with custom API key and max_tokens
+custom_api_key = "your_custom_api_key"
+api = GPT4VisionAPI(openai_api_key=custom_api_key, max_tokens=500)
 ```
 
-- `img_path` (str): The file path or URL of the image to be processed.
+### Methods<a name="methods"></a>
 
-### `__call__`
+#### encode_image<a name="encode_image"></a>
 
-The `__call__` method is the main method for interacting with the GPT-4 Vision model. It sends the image and tasks to the model and returns the generated response.
+This method allows you to encode an image from a URL to base64 format. It's a utility function used internally by the module.
 
 ```python
-response = gpt4vision(img, tasks)
-```
-
-- `img` (Union[str, List[str]]): Either a single image URL or a list of image URLs to be used for the API request.
-- `tasks` (List[str]): A list of tasks or questions related to the image(s).
-
-This method returns a `GPT4VisionResponse` object, which contains the generated answer.
-
-### `run`
+def encode_image(img: str) -> str:
+    """
+    Encode image to base64.
 
-The `run` method is an alternative way to interact with the GPT-4 Vision model. It takes a single task and image URL as input and returns the generated response.
+    Parameters:
+    - img (str): URL of the image to encode.
 
-```python
-response = gpt4vision.run(task, img)
+    Returns:
+    str: Base64 encoded image.
+    """
 ```
 
-- `task` (str): The task or question related to the image.
-- `img` (str): The image URL to be used for the API request.
-
-This method simplifies interactions when dealing with a single task and image.
-
-### `arun`
+#### run<a name="run"></a>
 
-The `arun` method is an asynchronous version of the `run` method. It allows for asynchronous processing of API requests, which can be useful in certain scenarios.
+The `run` method is the primary way to interact with the GPT-4 Vision model. It sends a request to the model with a task and an image URL, and it returns the model's response.
 
 ```python
-import asyncio
+def run(task: str, img: str) -> str:
+    """
+    Run the GPT-4 Vision model.
 
-async def main():
-    response = await gpt4vision.arun(task, img)
-    print(response)
+    Parameters:
+    - task (str): The task or question related to the image.
+    - img (str): URL of the image to analyze.
 
-loop = asyncio.get_event_loop()
-loop.run_until_complete(main())
+    Returns:
+    str: The model's response.
+    """
 ```
 
-- `task` (str): The task or question related to the image.
-- `img` (str): The image URL to be used for the API request.
-
-## Configuration Options
-
-The `GPT4Vision` class provides several configuration options that allow you to customize its behavior:
+#### __call__<a name="__call__"></a>
 
-- `max_retries` (int): The maximum number of retries to make to the API. Default: 3
-- `backoff_factor` (float): The backoff factor to use for exponential backoff. Default: 2.0
-- `timeout_seconds` (int): The timeout in seconds for the API request. Default: 10
-- `api_key` (str): The API key to use for the API request. Default: None (set via environment variable)
-- `quality` (str): The quality of the image to generate. Options: 'low' or 'high'. Default: 'low'
-- `max_tokens` (int): The maximum number of tokens to use for the API request. Default: 200
-
-## Usage Examples
-
-### Example 1: Generating Image Descriptions
-
-```python
-gpt4vision = GPT4Vision()
-img = "https://example.com/image.jpg"
-tasks = ["Describe this image."]
-response = gpt4vision(img, tasks)
-print(response.answer)
-```
-
-In this example, we create an instance of `GPT4Vision`, provide an image URL, and ask the model to describe the image. The response contains the generated description.
-
-### Example 2: Custom Configuration
+The `__call__` method is a convenient way to run the GPT-4 Vision model. It has the same functionality as the `run` method.
 
 ```python
-custom_config = {
-    "max_retries": 5,
-    "timeout_seconds": 20,
-    "quality": "high",
-    "max_tokens": 300,
-}
-gpt4vision = GPT4Vision(**custom_config)
-img = "https://example.com/another_image.jpg"
-tasks = ["What objects can you identify in this image?"]
-response = gpt4vision(img, tasks)
-print(response.answer)
-```
+def __call__(task: str, img: str) -> str:
+    """
+    Run the GPT-4 Vision model (callable).
 
-In this example, we create an instance of `GPT4Vision` with custom configuration options. We set a higher timeout, request high-quality images, and allow more tokens in the response.
+    Parameters:
+    - task (str): The task or question related to the image.
+    - img
 
-### Example 3: Using the `run` Method
+ (str): URL of the image to analyze.
 
-```python
-gpt4vision = GPT4Vision()
-img = "https://example.com/image.jpg"
-task = "Describe this image in detail."
-response = gpt4vision.run(task, img)
-print(response)
+    Returns:
+    str: The model's response.
+    """
 ```
 
-In this example, we use the `run` method to simplify the interaction by providing a single task and image URL.
+## Examples<a name="examples"></a>
 
-# Model Usage and Image Understanding
+Let's explore some usage examples of the `GPT4VisionAPI` module to better understand how to use it effectively.
 
-The GPT-4 Vision model processes images in a unique way, allowing it to answer questions about both or each of the images independently. Here's an overview:
+### Example 1: Basic Usage<a name="example-1-basic-usage"></a>
 
-| Purpose                                 | Description                                                                                                      |
-| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
-| Image Understanding                      | The model is shown two copies of the same image and can answer questions about both or each of the images independently. |
+In this example, we'll use the module with the default API key and maximum tokens to analyze an image.
 
-# Image Detail Control
+```python
+from swarms.models import GPT4VisionAPI
 
-You have control over how the model processes the image and generates textual understanding by using the `detail` parameter, which has two options: `low` and `high`.
+# Initialize with default API key and max_tokens
+api = GPT4VisionAPI()
 
-| Detail   | Description                                                                                                                                                                              |
-| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| low      | Disables the "high-res" model. The model receives a low-res 512 x 512 version of the image and represents the image with a budget of 65 tokens. Ideal for use cases not requiring high detail. |
-| high     | Enables "high-res" mode. The model first sees the low-res image and then creates detailed crops of input images as 512px squares based on the input image size. Uses a total of 129 tokens.  |
+# Define the task and image URL
+task = "What is the color of the object?"
+img = "https://i.imgur.com/2M2ZGwC.jpeg"
 
-# Managing Images
+# Run the GPT-4 Vision model
+response = api.run(task, img)
 
-To use the Chat Completions API effectively, you must manage the images you pass to the model. Here are some key considerations:
+# Print the model's response
+print(response)
+```
 
-| Management Aspect        | Description                                                                                       |
-| ------------------------- | ------------------------------------------------------------------------------------------------- |
-| Image Reuse              | To pass the same image multiple times, include the image with each API request.                  |
-| Image Size Optimization   | Improve latency by downsizing images to meet the expected size requirements.                    |
-| Image Deletion           | After processing, images are deleted from OpenAI servers and not retained. No data is used for training. |
+### Example 2: Custom API Key<a name="example-2-custom-api-key"></a>
 
-# Limitations
+If you have a custom API key, you can initialize the module with it as shown in this example.
 
-While GPT-4 with Vision is powerful, it has some limitations:
+```python
+from swarms.models import GPT4VisionAPI
 
-| Limitation                                   | Description                                                                                         |
-| -------------------------------------------- | --------------------------------------------------------------------------------------------------- |
-| Medical Images                               | Not suitable for interpreting specialized medical images like CT scans.                                |
-| Non-English Text                            | May not perform optimally when handling non-Latin alphabets, such as Japanese or Korean.               |
-| Large Text in Images                        | Enlarge text within images for readability, but avoid cropping important details.                       |
-| Rotated or Upside-Down Text/Images          | May misinterpret rotated or upside-down text or images.                                                  |
-| Complex Visual Elements                     | May struggle to understand complex graphs or text with varying colors or styles.                        |
-| Spatial Reasoning                            | Struggles with tasks requiring precise spatial localization, such as identifying chess positions.       |
-| Accuracy                                     | May generate incorrect descriptions or captions in certain scenarios.                                    |
-| Panoramic and Fisheye Images                | Struggles with panoramic and fisheye images.                                                              |
+# Initialize with custom API key and max_tokens
+custom_api_key = "your_custom_api_key"
+api = GPT4VisionAPI(openai_api_key=custom_api_key, max_tokens=500)
 
-# Calculating Costs
+# Define the task and image URL
+task = "What is the object in the image?"
+img = "https://i.imgur.com/3T3ZHwD.jpeg"
 
-Image inputs are metered and charged in tokens. The token cost depends on the image size and detail option.
+# Run the GPT-4 Vision model
+response = api.run(task, img)
 
-| Example                                       | Token Cost  |
-| --------------------------------------------- | ----------- |
-| 1024 x 1024 square image in detail: high mode | 765 tokens  |
-| 2048 x 4096 image in detail: high mode        | 1105 tokens |
-| 4096 x 8192 image in detail: low mode         | 85 tokens   |
+# Print the model's response
+print(response)
+```
 
-# FAQ
+### Example 3: Adjusting Maximum Tokens<a name="example-3-adjusting-maximum-tokens"></a>
 
-Here are some frequently asked questions about GPT-4 with Vision:
+You can also customize the maximum token limit when initializing the module. In this example, we set it to 1000 tokens.
 
-| Question                                     | Answer                                                                                             |
-| -------------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| Fine-Tuning Image Capabilities                | No, fine-tuning the image capabilities of GPT-4 is not supported at this time.                         |
-| Generating Images                            | GPT-4 is used for understanding images, not generating them.                                            |
-| Supported Image File Types                   | Supported image file types include PNG (.png), JPEG (.jpeg and .jpg), WEBP (.webp), and non-animated GIF (.gif). |
-| Image Size Limitations                       | Image uploads are restricted to 20MB per image.                                                           |
-| Image Deletion                               | Uploaded images are automatically deleted after processing by the model.                                   |
-| Learning More                               | For more details about GPT-4 with Vision, refer to the GPT-4 with Vision system card.                      |
-| CAPTCHA Submission                           | CAPTCHAs are blocked for safety reasons.                                                                  |
-| Rate Limits                                  | Image processing counts toward your tokens per minute (TPM) limit. Refer to the calculating costs section for details. |
-| Image Metadata                               | The model does not receive image metadata.                                                                |
-| Handling Unclear Images                      | If an image is unclear, the model will do its best to interpret it, but results may be less accurate.   |
+```python
+from swarms.models import GPT4VisionAPI
 
+# Initialize with default API key and custom max_tokens
+api = GPT4VisionAPI(max_tokens=1000)
 
+# Define the task and image URL
+task = "Describe the scene in the image."
+img = "https://i.imgur.com/4P4ZRxU.jpeg"
 
-## Additional Tips
+# Run the GPT-4 Vision model
+response = api.run(task, img)
 
-- Make sure to handle potential exceptions and errors when making API requests. The library includes retries and error handling, but it's essential to handle exceptions gracefully in your code.
-- Experiment with different configuration options to optimize the trade-off between response quality and response time based on your specific requirements.
+# Print the model's response
+print(response)
+```
 
-## References and Resources
+## Additional Information<a name="additional-information"></a>
 
-- [OpenAI Platform](https://beta.openai.com/signup/): Sign up for an OpenAI API key.
-- [OpenAI API Documentation](https://platform.openai.com/docs/api-reference/chat/create): Official API documentation for the GPT-4 Vision model.
+- If you encounter any errors or issues with the module, make sure to check your API key and internet connectivity.
+- It's recommended to handle exceptions when using the module to gracefully handle errors.
+- You can further customize the module to fit your specific use case by modifying the code as needed.
 
-Now you have a comprehensive understanding of the GPT4Vision Model API, its configuration options, and how to use it for various computer vision and natural language processing tasks. Start experimenting and integrating it into your projects to leverage the power of GPT-4 Vision for image-related tasks.
+## References<a name="references"></a>
 
-# Conclusion
+- [OpenAI API Documentation](https://beta.openai.com/docs/)
 
-With GPT-4 Vision, you have a powerful tool for understanding and generating textual descriptions for images. By considering its capabilities, limitations, and cost calculations, you can effectively leverage this model for various image-related tasks.
\ No newline at end of file
+This documentation provides a comprehensive guide on how to use the `GPT4VisionAPI` module effectively. It covers initialization, methods, usage examples, and additional information to ensure a smooth experience when working with the GPT-4 Vision model.
\ No newline at end of file
diff --git a/docs/swarms/models/huggingface.md b/docs/swarms/models/huggingface.md
index e429f080..8606d8f2 100644
--- a/docs/swarms/models/huggingface.md
+++ b/docs/swarms/models/huggingface.md
@@ -96,7 +96,7 @@ Here are three ways to use the `HuggingfaceLLM` class:
 from swarms.models import HuggingfaceLLM
 
 # Initialize the HuggingfaceLLM instance with a model ID
-model_id = "gpt2-small"
+model_id = "NousResearch/Nous-Hermes-2-Vision-Alpha"
 inference = HuggingfaceLLM(model_id=model_id)
 
 # Generate text based on a prompt
@@ -116,7 +116,7 @@ custom_config = {
     "quantization_config": {"load_in_4bit": True},
     "verbose": True
 }
-inference = HuggingfaceLLM(model_id="gpt2-small", **custom_config)
+inference = HuggingfaceLLM(model_id="NousResearch/Nous-Hermes-2-Vision-Alpha", **custom_config)
 
 # Generate text based on a prompt
 prompt_text = "Tell me a joke"
diff --git a/docs/swarms/structs/flow.md b/docs/swarms/structs/agent.md
similarity index 66%
rename from docs/swarms/structs/flow.md
rename to docs/swarms/structs/agent.md
index 13f0541c..f04bba02 100644
--- a/docs/swarms/structs/flow.md
+++ b/docs/swarms/structs/agent.md
@@ -1,14 +1,14 @@
-# `Flow` Documentation
+# `Agent` Documentation
 
 ## Overview
 
-The `Flow` class is a Python module designed to facilitate interactions with a language model, particularly one that operates as an autonomous agent. This class is part of a larger framework aimed at creating conversational agents using advanced language models like GPT-3. It enables you to establish a conversational loop with the model, generate responses, collect feedback, and control the flow of the conversation.
+The `Agent` class is a Python module designed to facilitate interactions with a language model, particularly one that operates as an autonomous agent. This class is part of a larger framework aimed at creating conversational agents using advanced language models like GPT-3. It enables you to establish a conversational loop with the model, generate responses, collect feedback, and control the agent of the conversation.
 
-In this documentation, you will learn how to use the `Flow` class effectively, its purpose, and how it can be integrated into your projects.
+In this documentation, you will learn how to use the `Agent` class effectively, its purpose, and how it can be integrated into your projects.
 
 ## Purpose
 
-The `Flow` class serves several key purposes:
+The `Agent` class serves several key purposes:
 
 1. **Conversational Loop**: It establishes a conversational loop with a language model. This means it allows you to interact with the model in a back-and-forth manner, taking turns in the conversation.
 
@@ -20,10 +20,10 @@ The `Flow` class serves several key purposes:
 
 ## Class Definition
 
-The `Flow` class has the following constructor:
+The `Agent` class has the following constructor:
 
 ```python
-class Flow:
+class Agent:
     def __init__(
         self,
         llm: Any,
@@ -49,18 +49,18 @@ class Flow:
 
 ## Usage
 
-The `Flow` class can be used to create a conversational loop with the language model. Here's how you can use it:
+The `Agent` class can be used to create a conversational loop with the language model. Here's how you can use it:
 
 ```python
-from swarms.structs import Flow
+from swarms.structs import Agent
 
-flow = Flow(llm=my_language_model, max_loops=5)
+agent = Agent(llm=my_language_model, max_loops=5)
 
 # Define a starting task or message
 initial_task = "Generate a 10,000 word blog on health and wellness."
 
 # Run the conversation loop
-final_response = flow.run(initial_task)
+final_response = agent.run(initial_task)
 ```
 
 ### Feedback
@@ -68,7 +68,7 @@ final_response = flow.run(initial_task)
 You can collect feedback during the conversation using the `provide_feedback` method:
 
 ```python
-flow.provide_feedback("Generate an SOP for new sales employees on the best cold sales practices")
+agent.provide_feedback("Generate an SOP for new sales employees on the best cold sales practices")
 ```
 
 ### Stopping Condition
@@ -76,12 +76,12 @@ flow.provide_feedback("Generate an SOP for new sales employees on the best cold
 You can define a custom stopping condition using a function. For example, you can stop the conversation if the response contains the word "Stop":
 
 ```python
-from swarms.structs import Flow
+from swarms.structs import Agent
 
 def stop_when_repeats(response: str) -> bool:
     return "Stop" in response.lower()
 
-flow = Flow(llm=my_language_model, max_loops=5, stopping_condition=stop_when_repeats)
+agent = Agent(llm=my_language_model, max_loops=5, stopping_condition=stop_when_repeats)
 ```
 
 ### Retry Mechanism
@@ -89,7 +89,7 @@ flow = Flow(llm=my_language_model, max_loops=5, stopping_condition=stop_when_rep
 If the response generation fails, the class will retry up to the specified number of attempts:
 
 ```python
-flow = Flow(llm=my_language_model, max_loops=5, retry_attempts=3)
+agent = Agent(llm=my_language_model, max_loops=5, retry_attempts=3)
 ```
 
 ## Additional Information
@@ -107,45 +107,45 @@ Here are three usage examples:
 ### Example 1: Simple Conversation
 
 ```python
-from swarms.structs import Flow
+from swarms.structs import Agent
 # Select any Language model from the models folder
 from swarms.models import Mistral, OpenAIChat
 
 llm = Mistral()
 # llm = OpenAIChat()
 
-flow = Flow(llm=llm, max_loops=5)
+agent = Agent(llm=llm, max_loops=5)
 
 # Define a starting task or message
 initial_task = "Generate an long form analysis on the transformer model architecture."
 
 # Run the conversation loop
-final_response = flow.run(initial_task)
+final_response = agent.run(initial_task)
 ```
 
 ### Example 2: Custom Stopping Condition
 
 ```python
-from swarms.structs import Flow
+from swarms.structs import Agent
 
 def stop_when_repeats(response: str) -> bool:
     return "Stop" in response.lower()
 
-flow = Flow(llm=llm, max_loops=5, stopping_condition=stop_when_repeats)
+agent = Agent(llm=llm, max_loops=5, stopping_condition=stop_when_repeats)
 ```
 
 ### Example 3: Interactive Conversation
 
 ```python
-from swarms.structs import Flow
+from swarms.structs import Agent
 
-flow = Flow(llm=llm, max_loops=5, interactive=True)
+agent = Agent(llm=llm, max_loops=5, interactive=True)
 
 # Provide initial task
 initial_task = "Rank and prioritize the following financial documents and cut out 30% of our expenses"
 
 # Run the conversation loop
-final_response = flow.run(initial_task)
+final_response = agent.run(initial_task)
 ```
 
 ## References and Resources
@@ -154,4 +154,4 @@ final_response = flow.run(initial_task)
 
 ## Conclusion
 
-The `Flow` class provides a powerful way to interact with language models in a conversational manner. By defining custom stopping conditions, collecting feedback, and controlling the flow of the conversation, you can create engaging and interactive applications that make use of advanced language models.
\ No newline at end of file
+The `Agent` class provides a powerful way to interact with language models in a conversational manner. By defining custom stopping conditions, collecting feedback, and controlling the agent of the conversation, you can create engaging and interactive applications that make use of advanced language models.
\ No newline at end of file
diff --git a/docs/swarms/structs/sequential_workflow.md b/docs/swarms/structs/sequential_workflow.md
index 12b38409..6f6d8954 100644
--- a/docs/swarms/structs/sequential_workflow.md
+++ b/docs/swarms/structs/sequential_workflow.md
@@ -22,9 +22,9 @@ Before delving into the details of the **SequentialWorkflow** class, let's defin
 
 A **task** refers to a specific unit of work that needs to be executed as part of the workflow. Each task is associated with a description and can be implemented as a callable object, such as a function or a model.
 
-### Flow
+### Agent
 
-A **flow** represents a callable object that can be a task within the **SequentialWorkflow**. Flows encapsulate the logic and functionality of a particular task. Flows can be functions, models, or any callable object that can be executed.
+A **agent** represents a callable object that can be a task within the **SequentialWorkflow**. Agents encapsulate the logic and functionality of a particular task. Agents can be functions, models, or any callable object that can be executed.
 
 ### Sequential Execution
 
@@ -70,7 +70,7 @@ The **SequentialWorkflow** class is versatile and can be employed in a wide rang
 
 2. **Workflow Creation**: Create an instance of the **SequentialWorkflow** class. Specify the maximum number of loops the workflow should run and whether a dashboard should be displayed.
 
-3. **Task Addition**: Add tasks to the workflow using the `add` method. Each task should be described using a human-readable description, and the associated flow (callable object) should be provided. Additional arguments and keyword arguments can be passed to the task.
+3. **Task Addition**: Add tasks to the workflow using the `add` method. Each task should be described using a human-readable description, and the associated agent (callable object) should be provided. Additional arguments and keyword arguments can be passed to the task.
 
 4. **Task Execution**: Execute the workflow using the `run` method. The tasks within the workflow will be executed sequentially, with task results passed as inputs to subsequent tasks.
 
@@ -93,10 +93,10 @@ Let's begin with a quick example to demonstrate how to create and run a Sequenti
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
-# Initialize the language model flow (e.g., GPT-3)
+# Initialize the language model agent (e.g., GPT-3)
 llm = OpenAIChat(
     openai_api_key="YOUR_API_KEY",
     temperature=0.5,
@@ -104,8 +104,8 @@ llm = OpenAIChat(
 )
 
 # Initialize flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
@@ -134,13 +134,13 @@ The `Task` class represents an individual task in the workflow. A task is essent
 
 ```python
 class Task:
-    def __init__(self, description: str, flow: Union[Callable, Flow], args: List[Any] = [], kwargs: Dict[str, Any] = {}, result: Any = None, history: List[Any] = [])
+    def __init__(self, description: str, agent: Union[Callable, Agent], args: List[Any] = [], kwargs: Dict[str, Any] = {}, result: Any = None, history: List[Any] = [])
 ```
 
 ### Parameters
 
 - `description` (str): A description of the task.
-- `flow` (Union[Callable, Flow]): The callable object representing the task. It can be a function, class, or a `Flow` instance.
+- `agent` (Union[Callable, Agent]): The callable object representing the task. It can be a function, class, or a `Agent` instance.
 - `args` (List[Any]): A list of positional arguments to pass to the task when executed. Default is an empty list.
 - `kwargs` (Dict[str, Any]): A dictionary of keyword arguments to pass to the task when executed. Default is an empty dictionary.
 - `result` (Any): The result of the task's execution. Default is `None`.
@@ -156,7 +156,7 @@ Execute the task.
 def execute(self):
 ```
 
-This method executes the task and updates the `result` and `history` attributes of the task. It checks if the task is a `Flow` instance and if the 'task' argument is needed.
+This method executes the task and updates the `result` and `history` attributes of the task. It checks if the task is a `Agent` instance and if the 'task' argument is needed.
 
 ## Class: `SequentialWorkflow`
 
@@ -182,15 +182,15 @@ class SequentialWorkflow:
 
 ### Methods
 
-#### `add(task: str, flow: Union[Callable, Flow], *args, **kwargs)`
+#### `add(task: str, agent: Union[Callable, Agent], *args, **kwargs)`
 
 Add a task to the workflow.
 
 ```python
-def add(self, task: str, flow: Union[Callable, Flow], *args, **kwargs) -> None:
+def add(self, task: str, agent: Union[Callable, Agent], *args, **kwargs) -> None:
 ```
 
-This method adds a new task to the workflow. You can provide a description of the task, the callable object (function, class, or `Flow` instance), and any additional positional or keyword arguments required for the task.
+This method adds a new task to the workflow. You can provide a description of the task, the callable object (function, class, or `Agent` instance), and any additional positional or keyword arguments required for the task.
 
 #### `reset_workflow()`
 
@@ -262,7 +262,7 @@ Run the workflow sequentially.
 def run(self) -> None:
 ```
 
-This method executes the tasks in the workflow sequentially. It checks if a task is a `Flow` instance and handles the flow of data between tasks accordingly.
+This method executes the tasks in the workflow sequentially. It checks if a task is a `Agent` instance and handles the agent of data between tasks accordingly.
 
 #### `arun()`
 
@@ -272,7 +272,7 @@ Asynchronously run the workflow.
 async def arun(self) -> None:
 ```
 
-This method asynchronously executes the tasks in the workflow sequentially. It's suitable for use cases where asynchronous execution is required. It also handles data flow between tasks.
+This method asynchronously executes the tasks in the workflow sequentially. It's suitable for use cases where asynchronous execution is required. It also handles data agent between tasks.
 
 #### `workflow_bootup(**kwargs)`
 
@@ -306,7 +306,7 @@ In this example, we'll create a Sequential Workflow and add tasks to it.
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -314,16 +314,16 @@ api_key = (
     ""  # Your actual API key here
 )
 
-# Initialize the language flow
+# Initialize the language agent
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
     max_tokens=3000,
 )
 
-# Initialize Flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize Agents for individual tasks
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
@@ -346,7 +346,7 @@ In this example, we'll create a Sequential Workflow, add tasks to it, and then r
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -354,16 +354,16 @@ api_key = (
     ""  # Your actual API key here
 )
 
-# Initialize the language flow
+# Initialize the language agent
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
     max_tokens=3000,
 )
 
-# Initialize Flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize Agents for individual tasks
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
@@ -389,7 +389,7 @@ In this example, we'll create a Sequential Workflow, add tasks to it, run the wo
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -397,16 +397,16 @@ api_key = (
     ""  # Your actual API key here
 )
 
-# Initialize the language flow
+# Initialize the language agent
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
     max_tokens=3000,
 )
 
-# Initialize Flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize Agents for individual tasks
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
@@ -432,7 +432,7 @@ In this example, we'll create a Sequential Workflow, add tasks to it, and then r
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -440,16 +440,16 @@ api_key = (
     ""  # Your actual API key here
 )
 
-# Initialize the language flow
+# Initialize the language agent
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
     max_tokens=3000,
 )
 
-# Initialize Flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize Agents for individual tasks
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
@@ -475,7 +475,7 @@ In this example, we'll create a Sequential Workflow, add tasks to it, and then u
 
 ```python
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -483,16 +483,16 @@ api_key = (
     ""  # Your actual API key here
 )
 
-# Initialize the language flow
+# Initialize the language agent
 llm = OpenAIChat(
     openai_api_key=api_key,
     temperature=0.5,
     max_tokens=3000,
 )
 
-# Initialize Flows for individual tasks
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize Agents for individual tasks
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the Sequential Workflow
 workflow = SequentialWorkflow(max_loops=1)
@@ -579,11 +579,11 @@ In summary, the Sequential Workflow module provides a foundation for orchestrati
 
 ## Frequently Asked Questions (FAQs)
 
-### Q1: What is the difference between a task and a flow in Sequential Workflows?
+### Q1: What is the difference between a task and a agent in Sequential Workflows?
 
 **A1:** In Sequential Workflows, a **task** refers to a specific unit of work that needs to be executed. It can be implemented as a callable object, such as a Python function, and is the fundamental building block of a workflow.
 
-A **flow**, on the other hand, is an encapsulation of a task within the workflow. Flows define the order in which tasks are executed and can be thought of as task containers. They allow you to specify dependencies, error handling, and other workflow-related configurations.
+A **agent**, on the other hand, is an encapsulation of a task within the workflow. Agents define the order in which tasks are executed and can be thought of as task containers. They allow you to specify dependencies, error handling, and other workflow-related configurations.
 
 ### Q2: Can I run tasks in parallel within a Sequential Workflow?
 
diff --git a/docs/swarms/swarms/groupchat.md b/docs/swarms/swarms/groupchat.md
index b881513f..bf9cbaad 100644
--- a/docs/swarms/swarms/groupchat.md
+++ b/docs/swarms/swarms/groupchat.md
@@ -4,7 +4,7 @@
 
 ## Overview
 
-The Swarms framework is a Python library designed to facilitate the creation and management of a simulated group chat environment. This environment can be used for a variety of purposes, such as training conversational agents, role-playing games, or simulating dialogues for machine learning purposes. The core functionality revolves around managing the flow of messages between different agents within the chat, as well as handling the selection and responses of these agents based on the conversation's context.
+The Swarms framework is a Python library designed to facilitate the creation and management of a simulated group chat environment. This environment can be used for a variety of purposes, such as training conversational agents, role-playing games, or simulating dialogues for machine learning purposes. The core functionality revolves around managing the agent of messages between different agents within the chat, as well as handling the selection and responses of these agents based on the conversation's context.
 
 ### Purpose
 
@@ -13,7 +13,7 @@ The purpose of the Swarms framework, and specifically the `GroupChat` and `Group
 ### Key Features
 
 - **Agent Interaction**: Allows multiple agents to communicate within a group chat scenario.
-- **Message Management**: Handles the storage and flow of messages within the group chat.
+- **Message Management**: Handles the storage and agent of messages within the group chat.
 - **Role Play**: Enables agents to assume specific roles and interact accordingly.
 - **Conversation Context**: Maintains the context of the conversation for appropriate responses by agents.
 
@@ -29,7 +29,7 @@ The `GroupChat` class is the backbone of the Swarms framework's chat simulation.
 
 | Parameter  | Type                | Description                                                  | Default Value |
 |------------|---------------------|--------------------------------------------------------------|---------------|
-| agents     | List[Flow]          | List of agent flows participating in the group chat.         | None          |
+| agents     | List[Agent]          | List of agent flows participating in the group chat.         | None          |
 | messages   | List[Dict]          | List of message dictionaries exchanged in the group chat.    | None          |
 | max_round  | int                 | Maximum number of rounds/messages allowed in the group chat. | 10            |
 | admin_name | str                 | The name of the admin agent in the group chat.               | "Admin"       |
@@ -38,10 +38,10 @@ The `GroupChat` class is the backbone of the Swarms framework's chat simulation.
 
 - `agent_names`: Returns a list of the names of the agents in the group chat.
 - `reset()`: Clears all messages from the group chat.
-- `agent_by_name(name: str) -> Flow`: Finds and returns an agent by name.
-- `next_agent(agent: Flow) -> Flow`: Returns the next agent in the list.
+- `agent_by_name(name: str) -> Agent`: Finds and returns an agent by name.
+- `next_agent(agent: Agent) -> Agent`: Returns the next agent in the list.
 - `select_speaker_msg() -> str`: Returns the message for selecting the next speaker.
-- `select_speaker(last_speaker: Flow, selector: Flow) -> Flow`: Logic to select the next speaker based on the last speaker and the selector agent.
+- `select_speaker(last_speaker: Agent, selector: Agent) -> Agent`: Logic to select the next speaker based on the last speaker and the selector agent.
 - `_participant_roles() -> str`: Returns a string listing all participant roles.
 - `format_history(messages: List[Dict]) -> str`: Formats the history of messages for display or processing.
 
@@ -50,10 +50,10 @@ The `GroupChat` class is the backbone of the Swarms framework's chat simulation.
 #### Example 1: Initializing a GroupChat
 
 ```python
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 from swarms.groupchat import GroupChat
 
-# Assuming Flow objects (flow1, flow2, flow3) are initialized and configured
+# Assuming Agent objects (flow1, flow2, flow3) are initialized and configured
 agents = [flow1, flow2, flow3]
 group_chat = GroupChat(agents=agents, messages=[], max_round=10)
 ```
@@ -67,8 +67,8 @@ group_chat.reset()
 #### Example 3: Selecting a Speaker
 
 ```python
-last_speaker = agents[0]  # Assuming this is a Flow object representing the last speaker
-selector = agents[1]  # Assuming this is a Flow object with the selector role
+last_speaker = agents[0]  # Assuming this is a Agent object representing the last speaker
+selector = agents[1]  # Assuming this is a Agent object with the selector role
 
 next_speaker = group_chat.select_speaker(last_speaker, selector)
 ```
@@ -86,7 +86,7 @@ The `GroupChatManager` class acts as a controller for the `GroupChat` instance.
 | Parameter  | Type        | Description                                          |
 |------------|-------------|------------------------------------------------------|
 | groupchat  | GroupChat   | The GroupChat instance that the manager will handle. |
-| selector   | Flow        | The Flow object that selects the next speaker.       |
+| selector   | Agent        | The Agent object that selects the next speaker.       |
 
 #### Methods
 
@@ -98,7 +98,7 @@ The `GroupChatManager` class acts as a controller for the `GroupChat` instance.
 
 ```python
 from swarms.groupchat import GroupChat, GroupChatManager
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 
 # Initialize your agents and group chat as shown in previous examples
 chat_manager = GroupChatManager(groupchat=group_chat, selector=manager)
@@ -132,7 +132,7 @@ By leveraging the framework's features, users can create complex interaction sce
 
 **Q: Can the Swarms framework handle real-time interactions between agents?**
 
-A: The Swarms framework is designed to simulate group chat environments. While it does not handle real-time interactions as they would occur on a network, it can simulate the flow of conversation in a way that mimics real-time communication.
+A: The Swarms framework is designed to simulate group chat environments. While it does not handle real-time interactions as they would occur on a network, it can simulate the agent of conversation in a way that mimics real-time communication.
 
 **Q: Is the Swarms framework capable of natural language processing?**
 
@@ -152,7 +152,7 @@ A: The framework is can be integrated with any chat services. However, it could
 
 **Q: How does the `GroupChatManager` select the next speaker?**
 
-A: The `GroupChatManager` uses a selection mechanism, which is typically based on the conversation's context and the roles of the agents, to determine the next speaker. The specifics of this mechanism can be customized to match the desired flow of the conversation.
+A: The `GroupChatManager` uses a selection mechanism, which is typically based on the conversation's context and the roles of the agents, to determine the next speaker. The specifics of this mechanism can be customized to match the desired agent of the conversation.
 
 **Q: Can I contribute to the Swarms framework or suggest features?**
 
diff --git a/example.py b/example.py
index 46e8b33c..6ed2cbab 100644
--- a/example.py
+++ b/example.py
@@ -1,37 +1,33 @@
+import os
+
+from dotenv import load_dotenv
+
+# Import the OpenAIChat model and the Agent struct
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
+
+# Load the environment variables
+load_dotenv()
 
-# Initialize the language model, this model can be swapped out with Anthropic, ETC, Huggingface Models like Mistral, ETC
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
+
+# Initialize the language model
 llm = OpenAIChat(
-    # model_name="gpt-4"
-    # openai_api_key=api_key,
     temperature=0.5,
-    # max_tokens=100,
+    model_name="gpt-4",
+    openai_api_key=api_key,
 )
 
 
 ## Initialize the workflow
-flow = Flow(
+agent = Agent(
     llm=llm,
-    max_loops=2,
+    max_loops=1,
+    autosave=True,
     dashboard=True,
-    # tools=[search_api]
-    # stopping_condition=None,  # You can define a stopping condition as needed.
-    # loop_interval=1,
-    # retry_attempts=3,
-    # retry_interval=1,
-    # interactive=False,  # Set to 'True' for interactive mode.
-    # dynamic_temperature=False,  # Set to 'True' for dynamic temperature handling.
 )
 
-# out = flow.load_state("flow_state.json")
-# temp = flow.dynamic_temperature()
-# filter = flow.add_response_filter("Trump")
-out = flow.run(
-    "Generate a 10,000 word blog on mental clarity and the benefits of meditation."
-)
-# out = flow.validate_response(out)
-# out = flow.analyze_feedback(out)
-# out = flow.print_history_and_memory()
-# # out = flow.save_state("flow_state.json")
-# print(out)
+# Run the workflow on a task
+out = agent.run("Generate a 10,000 word blog on health and wellness.")
+print(out)
diff --git a/mkdocs.yml b/mkdocs.yml
index e70e1a39..f2f6294e 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -6,9 +6,6 @@ copyright: "&copy; APAC Corp, Inc."
 extra_css:
   - docs/assets/css/extra.css
 extra:
-  # analytics:
-  #   provider: google
-  #   property: G-QM8EDPSCB6
   social:
     - icon: fontawesome/solid/house
       link: assets/img/SwarmsLogoIcon.png
@@ -75,7 +72,8 @@ nav:
     - AbstractAgent: "swarms/agents/abstract_agent.md"
     - OmniModalAgent: "swarms/agents/omni_agent.md"
   - swarms.models:
-    - Language:  
+    - Language:
+      - BaseLLM: "swarms/models/base_llm.md"
       - Overview: "swarms/models/index.md"
       - HuggingFaceLLM: "swarms/models/huggingface.md"
       - Anthropic: "swarms/models/anthropic.md"
@@ -85,6 +83,7 @@ nav:
       - MPT7B: "swarms/models/mpt.md"
       - Mistral: "swarms/models/mistral.md"
     - MultiModal:
+      - BaseMultiModalModel: "swarms/models/base_multimodal_model.md"
       - Fuyu: "swarms/models/fuyu.md"
       - Vilt: "swarms/models/vilt.md"
       - Idefics: "swarms/models/idefics.md"
@@ -99,20 +98,18 @@ nav:
   - swarms.structs:
     - Overview: "swarms/structs/overview.md"
     - AutoScaler: "swarms/swarms/autoscaler.md"
-    - Flow: "swarms/structs/flow.md"
+    - Agent: "swarms/structs/agent.md"
     - SequentialWorkflow: 'swarms/structs/sequential_workflow.md'
   - swarms.memory:
     - PineconeVectorStoreStore: "swarms/memory/pinecone.md"
     - PGVectorStore: "swarms/memory/pg.md"
-  # - swarms.chunkers: 
-  #   - BaseChunker: "swarms/chunkers/basechunker.md"
-  #   - PdfChunker: "swarms/chunkers/pdf_chunker.md"
 - Guides:
     - Overview: "examples/index.md"
     - Agents:
-      - Flow: "examples/flow.md"
-      - SequentialWorkflow: "examples/reliable_autonomous_agents.md"
+      - Agent: "examples/flow.md"
       - OmniAgent: "examples/omni_agent.md"
+    - Swarms:
+      - SequentialWorkflow: "examples/reliable_autonomous_agents.md"
     - 2O+ Autonomous Agent Blogs: "examples/ideas.md"
 - Applications:
     - CustomerSupport: 
@@ -134,4 +131,4 @@ nav:
     - Architecture: "corporate/architecture.md"
     - Checklist: "corporate/checklist.md"
     - Hiring: "corporate/hiring.md"
-    - SwarmCloud: "corporate/swarm_cloud.md"
+    - SwarmCloud: "corporate/swarm_cloud.md"
\ No newline at end of file
diff --git a/multi_modal_auto_agent.py b/multi_modal_auto_agent.py
new file mode 100644
index 00000000..d32a6221
--- /dev/null
+++ b/multi_modal_auto_agent.py
@@ -0,0 +1,34 @@
+# Description: This is an example of how to use the Agent class to run a multi-modal workflow
+import os
+from dotenv import load_dotenv
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.structs import Agent
+
+# Load the environment variables
+load_dotenv()
+
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
+
+# Initialize the language model
+llm = GPT4VisionAPI(
+    openai_api_key=api_key,
+    max_tokens=500,
+)
+
+# Initialize the language model
+task = "What is the color of the object?"
+img = "images/swarms.jpeg"
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm,
+    max_loops="auto",
+    autosave=True,
+    dashboard=True,
+    multi_modal=True,
+)
+
+# Run the workflow on a task
+out = agent.run(task=task, img=img)
+print(out)
diff --git a/playground/agents/mm_agent_example.py b/playground/agents/mm_agent_example.py
index 0da0d469..6cedcb29 100644
--- a/playground/agents/mm_agent_example.py
+++ b/playground/agents/mm_agent_example.py
@@ -4,11 +4,16 @@ load_dict = {"ImageCaptioning": "cuda"}
 
 node = MultiModalAgent(load_dict)
 
-text = node.run_text("What is your name? Generate a picture of yourself")
+text = node.run_text(
+    "What is your name? Generate a picture of yourself"
+)
 
 img = node.run_img("/image1", "What is this image about?")
 
 chat = node.chat(
-    "What is your name? Generate a picture of yourself. What is this image about?",
+    (
+        "What is your name? Generate a picture of yourself. What is"
+        " this image about?"
+    ),
     streaming=True,
 )
diff --git a/playground/agents/revgpt_agent.py b/playground/agents/revgpt_agent.py
deleted file mode 100644
index 42d95359..00000000
--- a/playground/agents/revgpt_agent.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import os
-from dotenv import load_dotenv
-from swarms.models.revgptV4 import RevChatGPTModel
-from swarms.workers.worker import Worker
-
-load_dotenv()
-
-config = {
-    "model": os.getenv("REVGPT_MODEL"),
-    "plugin_ids": [os.getenv("REVGPT_PLUGIN_IDS")],
-    "disable_history": os.getenv("REVGPT_DISABLE_HISTORY") == "True",
-    "PUID": os.getenv("REVGPT_PUID"),
-    "unverified_plugin_domains": [os.getenv("REVGPT_UNVERIFIED_PLUGIN_DOMAINS")],
-}
-
-llm = RevChatGPTModel(access_token=os.getenv("ACCESS_TOKEN"), **config)
-
-worker = Worker(ai_name="Optimus Prime", llm=llm)
-
-task = "What were the winning boston marathon times for the past 5 years (ending in 2022)? Generate a table of the year, name, country of origin, and times."
-response = worker.run(task)
-print(response)
diff --git a/playground/agents/simple_agent.py b/playground/agents/simple_agent.py
index 515b83bc..b30d93c8 100644
--- a/playground/agents/simple_agent.py
+++ b/playground/agents/simple_agent.py
@@ -1,5 +1,5 @@
 from swarms.agents.simple_agent import SimpleAgent
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.models import OpenAIChat
 
 api_key = ""
@@ -9,8 +9,8 @@ llm = OpenAIChat(
     temperature=0.5,
 )
 
-# Initialize the flow
-flow = Flow(
+# Initialize the agent
+agent = Agent(
     llm=llm,
     max_loops=5,
 )
@@ -18,7 +18,7 @@ flow = Flow(
 
 agent = SimpleAgent(
     name="Optimus Prime",
-    flow=flow,
+    agent=agent,
     # Memory
 )
 
diff --git a/playground/demos/accountant_team/account_team2.py b/playground/demos/accountant_team/account_team2.py
index 4c13d2e9..1b9d3659 100644
--- a/playground/demos/accountant_team/account_team2.py
+++ b/playground/demos/accountant_team/account_team2.py
@@ -6,7 +6,7 @@ from swarms.prompts.accountant_swarm_prompts import (
     DOC_ANALYZER_AGENT_PROMPT,
     SUMMARY_GENERATOR_AGENT_PROMPT,
 )
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.utils.pdf_to_text import pdf_to_text
 
 # Environment variables
@@ -28,21 +28,21 @@ llm2 = Anthropic(
 
 
 # Agents
-doc_analyzer_agent = Flow(
+doc_analyzer_agent = Agent(
     llm=llm2,
     sop=DOC_ANALYZER_AGENT_PROMPT,
     max_loops=1,
     autosave=True,
     saved_state_path="doc_analyzer_agent.json",
 )
-summary_generator_agent = Flow(
+summary_generator_agent = Agent(
     llm=llm2,
     sop=SUMMARY_GENERATOR_AGENT_PROMPT,
     max_loops=1,
     autosave=True,
     saved_state_path="summary_generator_agent.json",
 )
-decision_making_support_agent = Flow(
+decision_making_support_agent = Agent(
     llm=llm2,
     sop=DECISION_MAKING_PROMPT,
     max_loops=1,
@@ -53,7 +53,8 @@ decision_making_support_agent = Flow(
 pdf_path = "bankstatement.pdf"
 fraud_detection_instructions = "Detect fraud in the document"
 summary_agent_instructions = (
-    "Generate an actionable summary of the document with action steps to take"
+    "Generate an actionable summary of the document with action steps"
+    " to take"
 )
 decision_making_support_agent_instructions = (
     "Provide decision making support to the business owner:"
@@ -77,5 +78,6 @@ summary_agent_output = summary_generator_agent.run(
 
 # Provide decision making support to the accountant
 decision_making_support_agent_output = decision_making_support_agent.run(
-    f"{decision_making_support_agent_instructions}: {summary_agent_output}"
+    f"{decision_making_support_agent_instructions}:"
+    f" {summary_agent_output}"
 )
diff --git a/playground/demos/accountant_team/accountant_team.py b/playground/demos/accountant_team/accountant_team.py
index 61cc2f7a..fccd628b 100644
--- a/playground/demos/accountant_team/accountant_team.py
+++ b/playground/demos/accountant_team/accountant_team.py
@@ -10,7 +10,7 @@ from swarms.prompts.accountant_swarm_prompts import (
     FRAUD_DETECTION_AGENT_PROMPT,
     SUMMARY_GENERATOR_AGENT_PROMPT,
 )
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.utils.pdf_to_text import pdf_to_text
 
 # Environment variables
@@ -30,15 +30,15 @@ llm2 = Anthropic(
 
 
 # Agents
-doc_analyzer_agent = Flow(
+doc_analyzer_agent = Agent(
     llm=llm1,
     sop=DOC_ANALYZER_AGENT_PROMPT,
 )
-summary_generator_agent = Flow(
+summary_generator_agent = Agent(
     llm=llm2,
     sop=SUMMARY_GENERATOR_AGENT_PROMPT,
 )
-decision_making_support_agent = Flow(
+decision_making_support_agent = Agent(
     llm=llm2,
     sop=DECISION_MAKING_PROMPT,
 )
@@ -49,7 +49,7 @@ class AccountantSwarms:
     Accountant Swarms is a collection of agents that work together to help
     accountants with their work.
 
-    Flow: analyze doc -> detect fraud -> generate summary -> decision making support
+    Agent: analyze doc -> detect fraud -> generate summary -> decision making support
 
     The agents are:
     - User Consultant: Asks the user many questions
@@ -81,7 +81,9 @@ class AccountantSwarms:
         super().__init__()
         self.pdf_path = pdf_path
         self.list_pdfs = list_pdfs
-        self.fraud_detection_instructions = fraud_detection_instructions
+        self.fraud_detection_instructions = (
+            fraud_detection_instructions
+        )
         self.summary_agent_instructions = summary_agent_instructions
         self.decision_making_support_agent_instructions = (
             decision_making_support_agent_instructions
@@ -98,12 +100,14 @@ class AccountantSwarms:
 
         # Generate an actionable summary of the document
         summary_agent_output = summary_generator_agent.run(
-            f"{self.summary_agent_instructions}: {fraud_detection_agent_output}"
+            f"{self.summary_agent_instructions}:"
+            f" {fraud_detection_agent_output}"
         )
 
         # Provide decision making support to the accountant
         decision_making_support_agent_output = decision_making_support_agent.run(
-            f"{self.decision_making_support_agent_instructions}: {summary_agent_output}"
+            f"{self.decision_making_support_agent_instructions}:"
+            f" {summary_agent_output}"
         )
 
         return decision_making_support_agent_output
@@ -112,6 +116,10 @@ class AccountantSwarms:
 swarm = AccountantSwarms(
     pdf_path="tesla.pdf",
     fraud_detection_instructions="Detect fraud in the document",
-    summary_agent_instructions="Generate an actionable summary of the document",
-    decision_making_support_agent_instructions="Provide decision making support to the business owner:",
+    summary_agent_instructions=(
+        "Generate an actionable summary of the document"
+    ),
+    decision_making_support_agent_instructions=(
+        "Provide decision making support to the business owner:"
+    ),
 )
diff --git a/playground/demos/ad_gen/ad_gen.py b/playground/demos/ad_gen/ad_gen.py
new file mode 100644
index 00000000..b665b63a
--- /dev/null
+++ b/playground/demos/ad_gen/ad_gen.py
@@ -0,0 +1,102 @@
+import random
+import os
+from dotenv import load_dotenv
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
+from swarms.models.stable_diffusion import StableDiffusion
+
+load_dotenv()
+openai_api_key = os.getenv("OPENAI_API_KEY")
+stability_api_key = os.getenv("STABILITY_API_KEY")
+
+# Initialize the language model and image generation model
+llm = OpenAIChat(
+    openai_api_key=openai_api_key, temperature=0.5, max_tokens=3000
+)
+sd_api = StableDiffusion(api_key=stability_api_key)
+
+
+# Creative Concept Generator for Product Ads
+class ProductAdConceptGenerator:
+    def __init__(self, product_name):
+        self.product_name = product_name
+        self.themes = [
+            "futuristic",
+            "rustic",
+            "luxurious",
+            "minimalistic",
+            "vibrant",
+            "elegant",
+            "retro",
+            "urban",
+            "ethereal",
+            "surreal",
+            "artistic",
+            "tech-savvy",
+            "vintage",
+            "natural",
+            "sophisticated",
+            "playful",
+            "dynamic",
+            "serene",
+            "lasers,lightning",
+        ]
+        self.contexts = [
+            "in an everyday setting",
+            "in a rave setting",
+            "in an abstract environment",
+            "in an adventurous context",
+            "surrounded by nature",
+            "in a high-tech setting",
+            "in a historical context",
+            "in a busy urban scene",
+            "in a tranquil and peaceful setting",
+            "against a backdrop of city lights",
+            "in a surreal dreamscape",
+            "in a festive atmosphere",
+            "in a luxurious setting",
+            "in a playful and colorful background",
+            "in an ice cave setting",
+            "in a serene and calm landscape",
+        ]
+        self.contexts = [
+            "high realism product ad (extremely creative)"
+        ]
+
+    def generate_concept(self):
+        theme = random.choice(self.themes)
+        context = random.choice(self.contexts)
+        return (
+            f"{theme} inside a {style} {self.product_name}, {context}"
+        )
+
+
+# User input
+product_name = input(
+    "Enter a product name for ad creation (e.g., 'PS5', 'AirPods',"
+    " 'Kirkland Vodka'): "
+)
+
+# Generate creative concept
+concept_generator = ProductAdConceptGenerator(product_name)
+creative_concept = concept_generator.generate_concept()
+
+# Generate product image based on the creative concept
+image_paths = sd_api.run(creative_concept)
+
+# Generate ad copy
+ad_copy_agent = Agent(llm=llm, max_loops=1)
+ad_copy_prompt = (
+    f"Write a compelling {social_media_platform} ad copy for a"
+    f" product photo showing {product_name} {creative_concept}."
+)
+ad_copy = ad_copy_agent.run(task=ad_copy_prompt)
+
+# Output the results
+print("Creative Concept:", concept_result)
+print("Design Ideas:", design_result)
+print("Ad Copy:", copywriting_result)
+print(
+    "Image Path:",
+    image_paths[0] if image_paths else "No image generated",
+)
diff --git a/playground/demos/ai_research_team/main.py b/playground/demos/ai_research_team/main.py
index a297bc0a..bda9e0de 100644
--- a/playground/demos/ai_research_team/main.py
+++ b/playground/demos/ai_research_team/main.py
@@ -7,7 +7,7 @@ from swarms.prompts.ai_research_team import (
     PAPER_IMPLEMENTOR_AGENT_PROMPT,
     PAPER_SUMMARY_ANALYZER,
 )
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.utils.pdf_to_text import pdf_to_text
 
 # Base llms
@@ -29,7 +29,7 @@ llm2 = Anthropic(
 )
 
 # Agents
-paper_summarizer_agent = Flow(
+paper_summarizer_agent = Agent(
     llm=llm2,
     sop=PAPER_SUMMARY_ANALYZER,
     max_loops=1,
@@ -37,7 +37,7 @@ paper_summarizer_agent = Flow(
     saved_state_path="paper_summarizer.json",
 )
 
-paper_implementor_agent = Flow(
+paper_implementor_agent = Agent(
     llm=llm1,
     sop=PAPER_IMPLEMENTOR_AGENT_PROMPT,
     max_loops=1,
@@ -48,6 +48,9 @@ paper_implementor_agent = Flow(
 
 paper = pdf_to_text(PDF_PATH)
 algorithmic_psuedocode_agent = paper_summarizer_agent.run(
-    f"Focus on creating the algorithmic pseudocode for the novel method in this paper: {paper}"
+    "Focus on creating the algorithmic pseudocode for the novel"
+    f" method in this paper: {paper}"
+)
+pytorch_code = paper_implementor_agent.run(
+    algorithmic_psuedocode_agent
 )
-pytorch_code = paper_implementor_agent.run(algorithmic_psuedocode_agent)
diff --git a/playground/demos/assembly/assembly.py b/playground/demos/assembly/assembly.py
new file mode 100644
index 00000000..b82e075c
--- /dev/null
+++ b/playground/demos/assembly/assembly.py
@@ -0,0 +1,24 @@
+from swarms.structs import Agent
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.prompts.multi_modal_autonomous_instruction_prompt import (
+    MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
+)
+
+llm = GPT4VisionAPI()
+
+task = (
+    "Analyze this image of an assembly line and identify any issues"
+    " such as misaligned parts, defects, or deviations from the"
+    " standard assembly process. IF there is anything unsafe in the"
+    " image, explain why it is unsafe and how it could be improved."
+)
+img = "assembly_line.jpg"
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm,
+    max_loops=1,
+    dashboard=True,
+)
+
+agent.run(task=task, img=img)
diff --git a/playground/demos/assembly/assembly_line.jpg b/playground/demos/assembly/assembly_line.jpg
new file mode 100644
index 00000000..df35c2e3
Binary files /dev/null and b/playground/demos/assembly/assembly_line.jpg differ
diff --git a/swarms/swarms/autobloggen.py b/playground/demos/autobloggen.py
similarity index 81%
rename from swarms/swarms/autobloggen.py
rename to playground/demos/autobloggen.py
index dec2620f..09b02674 100644
--- a/swarms/swarms/autobloggen.py
+++ b/playground/demos/autobloggen.py
@@ -9,7 +9,8 @@ from swarms.prompts.autobloggen import (
 
 # Prompts
 topic_selection_task = (
-    "Generate 10 topics on gaining mental clarity using ancient practices"
+    "Generate 10 topics on gaining mental clarity using ancient"
+    " practices"
 )
 
 
@@ -17,7 +18,7 @@ class AutoBlogGenSwarm:
     """
     AutoBlogGenSwarm
 
-    Swarm Flow
+    Swarm Agent
     Topic selection agent -> draft agent -> review agent -> distribution agent
 
     Topic Selection Agent:
@@ -54,7 +55,9 @@ class AutoBlogGenSwarm:
     ):
         self.llm = llm()
         self.topic_selection_task = topic_selection_task
-        self.topic_selection_agent_prompt = topic_selection_agent_prompt
+        self.topic_selection_agent_prompt = (
+            topic_selection_agent_prompt
+        )
         self.objective = objective
         self.iterations = iterations
         self.max_retries = max_retries
@@ -90,7 +93,9 @@ class AutoBlogGenSwarm:
 
     def step(self):
         """Steps through the task"""
-        topic_selection_agent = self.llm(self.topic_selection_agent_prompt)
+        topic_selection_agent = self.llm(
+            self.topic_selection_agent_prompt
+        )
         topic_selection_agent = self.print_beautifully(
             "Topic Selection Agent", topic_selection_agent
         )
@@ -100,10 +105,14 @@ class AutoBlogGenSwarm:
 
         # Agent that reviews the draft
         review_agent = self.llm(self.get_review_prompt(draft_blog))
-        review_agent = self.print_beautifully("Review Agent", review_agent)
+        review_agent = self.print_beautifully(
+            "Review Agent", review_agent
+        )
 
         # Agent that publishes on social media
-        distribution_agent = self.llm(self.social_media_prompt(article=review_agent))
+        distribution_agent = self.llm(
+            self.social_media_prompt(article=review_agent)
+        )
         distribution_agent = self.print_beautifully(
             "Distribution Agent", distribution_agent
         )
@@ -115,7 +124,15 @@ class AutoBlogGenSwarm:
                 for i in range(self.iterations):
                     self.step()
             except Exception as error:
-                print(colored(f"Error while running AutoBlogGenSwarm {error}", "red"))
+                print(
+                    colored(
+                        (
+                            "Error while running AutoBlogGenSwarm"
+                            f" {error}"
+                        ),
+                        "red",
+                    )
+                )
                 if attempt == self.retry_attempts - 1:
                     raise
 
diff --git a/playground/demos/autotemp/autotemp.py b/playground/demos/autotemp/autotemp.py
new file mode 100644
index 00000000..baf8f091
--- /dev/null
+++ b/playground/demos/autotemp/autotemp.py
@@ -0,0 +1,90 @@
+import re
+from swarms.models.openai_models import OpenAIChat
+
+
+class AutoTemp:
+    """
+    AutoTemp is a tool for automatically selecting the best temperature setting for a given task.
+    It generates responses at different temperatures, evaluates them, and ranks them based on quality.
+    """
+
+    def __init__(
+        self,
+        api_key,
+        default_temp=0.0,
+        alt_temps=None,
+        auto_select=True,
+        max_workers=6,
+    ):
+        self.api_key = api_key
+        self.default_temp = default_temp
+        self.alt_temps = (
+            alt_temps if alt_temps else [0.4, 0.6, 0.8, 1.0, 1.2, 1.4]
+        )
+        self.auto_select = auto_select
+        self.max_workers = max_workers
+        self.llm = OpenAIChat(
+            openai_api_key=self.api_key, temperature=self.default_temp
+        )
+
+    def evaluate_output(self, output, temperature):
+        print(f"Evaluating output at temperature {temperature}...")
+        eval_prompt = f"""
+        Evaluate the following output which was generated at a temperature setting of {temperature}. Provide a precise score from 0.0 to 100.0, considering the following criteria:
+
+        - Relevance: How well does the output address the prompt or task at hand?
+        - Clarity: Is the output easy to understand and free of ambiguity?
+        - Utility: How useful is the output for its intended purpose?
+        - Pride: If the user had to submit this output to the world for their career, would they be proud?
+        - Delight: Is the output likely to delight or positively surprise the user?
+
+        Be sure to comprehensively evaluate the output, it is very important for my career. Please answer with just the score with one decimal place accuracy, such as 42.0 or 96.9. Be extremely critical.
+
+        Output to evaluate:
+        ---
+        {output}
+        ---
+        """
+        score_text = self.llm(eval_prompt, temperature=0.5)
+        score_match = re.search(r"\b\d+(\.\d)?\b", score_text)
+        return (
+            round(float(score_match.group()), 1)
+            if score_match
+            else 0.0
+        )
+
+    def run(self, prompt, temperature_string):
+        print("Starting generation process...")
+        temperature_list = [
+            float(temp.strip())
+            for temp in temperature_string.split(",")
+            if temp.strip()
+        ]
+        outputs = {}
+        scores = {}
+        for temp in temperature_list:
+            print(f"Generating at temperature {temp}...")
+            output_text = self.llm(prompt, temperature=temp)
+            if output_text:
+                outputs[temp] = output_text
+                scores[temp] = self.evaluate_output(output_text, temp)
+
+        print("Generation process complete.")
+        if not scores:
+            return "No valid outputs generated.", None
+
+        sorted_scores = sorted(
+            scores.items(), key=lambda item: item[1], reverse=True
+        )
+        best_temp, best_score = sorted_scores[0]
+        best_output = outputs[best_temp]
+
+        return (
+            f"Best AutoTemp Output (Temp {best_temp} | Score:"
+            f" {best_score}):\n{best_output}"
+            if self.auto_select
+            else "\n".join(
+                f"Temp {temp} | Score: {score}:\n{outputs[temp]}"
+                for temp, score in sorted_scores
+            )
+        )
diff --git a/playground/demos/autotemp/autotemp_example.py b/playground/demos/autotemp/autotemp_example.py
new file mode 100644
index 00000000..c5f86416
--- /dev/null
+++ b/playground/demos/autotemp/autotemp_example.py
@@ -0,0 +1,22 @@
+from swarms.models import OpenAIChat
+from autotemp import AutoTemp
+
+# Your OpenAI API key
+api_key = ""
+
+autotemp_agent = AutoTemp(
+    api_key=api_key,
+    alt_temps=[0.4, 0.6, 0.8, 1.0, 1.2],
+    auto_select=False,
+    # model_version="gpt-3.5-turbo"  # Specify the model version if needed
+)
+
+# Define the task and temperature string
+task = "Generate a short story about a lost civilization."
+temperature_string = "0.4,0.6,0.8,1.0,1.2,"
+
+# Run the AutoTempAgent
+result = autotemp_agent.run(task, temperature_string)
+
+# Print the result
+print(result)
diff --git a/playground/demos/autotemp/blog_gen.py b/playground/demos/autotemp/blog_gen.py
new file mode 100644
index 00000000..e11a1521
--- /dev/null
+++ b/playground/demos/autotemp/blog_gen.py
@@ -0,0 +1,138 @@
+import os
+from termcolor import colored
+from swarms.models import OpenAIChat
+from autotemp import AutoTemp
+from swarms.structs import SequentialWorkflow
+
+
+class BlogGen:
+    def __init__(
+        self,
+        api_key,
+        blog_topic,
+        temperature_range: str = "0.4,0.6,0.8,1.0,1.2",
+    ):  # Add blog_topic as an argument
+        self.openai_chat = OpenAIChat(
+            openai_api_key=api_key, temperature=0.8
+        )
+        self.auto_temp = AutoTemp(api_key)
+        self.temperature_range = temperature_range
+        self.workflow = SequentialWorkflow(max_loops=5)
+
+        # Formatting the topic selection prompt with the user's topic
+        self.TOPIC_SELECTION_SYSTEM_PROMPT = f"""
+        Given the topic '{blog_topic}', generate an engaging and versatile blog topic. This topic should cover areas related to '{blog_topic}' and might include aspects such as current events, lifestyle, technology, health, and culture related to '{blog_topic}'. Identify trending subjects within this realm. The topic must be unique, thought-provoking, and have the potential to draw in readers interested in '{blog_topic}'.
+        """
+
+        self.DRAFT_WRITER_SYSTEM_PROMPT = """
+        Create an engaging and comprehensive blog article of at least 1,000 words on '{{CHOSEN_TOPIC}}'. The content should be original, informative, and reflective of a human-like style, with a clear structure including headings and sub-headings. Incorporate a blend of narrative, factual data, expert insights, and anecdotes to enrich the article. Focus on SEO optimization by using relevant keywords, ensuring readability, and including meta descriptions and title tags. The article should provide value, appeal to both knowledgeable and general readers, and maintain a balance between depth and accessibility. Aim to make the article engaging and suitable for online audiences.
+        """
+
+        self.REVIEW_AGENT_SYSTEM_PROMPT = """
+        Critically review the drafted blog article on '{{ARTICLE_TOPIC}}' to refine it to high-quality content suitable for online publication. Ensure the article is coherent, factually accurate, engaging, and optimized for search engines (SEO). Check for the effective use of keywords, readability, internal and external links, and the inclusion of meta descriptions and title tags. Edit the content to enhance clarity, impact, and maintain the authors voice. The goal is to polish the article into a professional, error-free piece that resonates with the target audience, adheres to publication standards, and is optimized for both search engines and social media sharing.
+        """
+
+        self.DISTRIBUTION_AGENT_SYSTEM_PROMPT = """
+        Develop an autonomous distribution strategy for the blog article on '{{ARTICLE_TOPIC}}'. Utilize an API to post the article on a popular blog platform (e.g., WordPress, Blogger, Medium) commonly used by our target audience. Ensure the post includes all SEO elements like meta descriptions, title tags, and properly formatted content. Craft unique, engaging social media posts tailored to different platforms to promote the blog article. Schedule these posts to optimize reach and engagement, using data-driven insights. Monitor the performance of the distribution efforts, adjusting strategies based on engagement metrics and audience feedback. Aim to maximize the article's visibility, attract a diverse audience, and foster engagement across digital channels.
+        """
+
+    def run_workflow(self):
+        try:
+            # Topic generation using OpenAIChat
+            topic_result = self.openai_chat.generate(
+                [self.TOPIC_SELECTION_SYSTEM_PROMPT]
+            )
+            topic_output = topic_result.generations[0][0].text
+            print(
+                colored(
+                    (
+                        "\nTopic Selection Task"
+                        f" Output:\n----------------------------\n{topic_output}\n"
+                    ),
+                    "white",
+                )
+            )
+
+            chosen_topic = topic_output.split("\n")[0]
+            print(
+                colored("Selected topic: " + chosen_topic, "yellow")
+            )
+
+            # Initial draft generation with AutoTemp
+            initial_draft_prompt = (
+                self.DRAFT_WRITER_SYSTEM_PROMPT.replace(
+                    "{{CHOSEN_TOPIC}}", chosen_topic
+                )
+            )
+            auto_temp_output = self.auto_temp.run(
+                initial_draft_prompt, self.temperature_range
+            )
+            initial_draft_output = auto_temp_output  # Assuming AutoTemp.run returns the best output directly
+            print(
+                colored(
+                    (
+                        "\nInitial Draft"
+                        f" Output:\n----------------------------\n{initial_draft_output}\n"
+                    ),
+                    "white",
+                )
+            )
+
+            # Review process using OpenAIChat
+            review_prompt = self.REVIEW_AGENT_SYSTEM_PROMPT.replace(
+                "{{ARTICLE_TOPIC}}", chosen_topic
+            )
+            review_result = self.openai_chat.generate([review_prompt])
+            review_output = review_result.generations[0][0].text
+            print(
+                colored(
+                    (
+                        "\nReview"
+                        f" Output:\n----------------------------\n{review_output}\n"
+                    ),
+                    "white",
+                )
+            )
+
+            # Distribution preparation using OpenAIChat
+            distribution_prompt = (
+                self.DISTRIBUTION_AGENT_SYSTEM_PROMPT.replace(
+                    "{{ARTICLE_TOPIC}}", chosen_topic
+                )
+            )
+            distribution_result = self.openai_chat.generate(
+                [distribution_prompt]
+            )
+            distribution_output = distribution_result.generations[0][
+                0
+            ].text
+            print(
+                colored(
+                    (
+                        "\nDistribution"
+                        f" Output:\n----------------------------\n{distribution_output}\n"
+                    ),
+                    "white",
+                )
+            )
+
+            # Final compilation of the blog
+            final_blog_content = f"{initial_draft_output}\n\n{review_output}\n\n{distribution_output}"
+            print(
+                colored(
+                    (
+                        "\nFinal Blog"
+                        f" Content:\n----------------------------\n{final_blog_content}\n"
+                    ),
+                    "green",
+                )
+            )
+
+        except Exception as e:
+            print(colored(f"An error occurred: {str(e)}", "red"))
+
+
+if __name__ == "__main__":
+    api_key = os.environ["OPENAI_API_KEY"]
+    blog_generator = BlogGen(api_key)
+    blog_generator.run_workflow()
diff --git a/playground/demos/autotemp/blog_gen_example.py b/playground/demos/autotemp/blog_gen_example.py
new file mode 100644
index 00000000..e7109b5a
--- /dev/null
+++ b/playground/demos/autotemp/blog_gen_example.py
@@ -0,0 +1,25 @@
+import os
+from blog_gen import BlogGen
+
+
+def main():
+    api_key = os.getenv("OPENAI_API_KEY")
+    if not api_key:
+        raise ValueError(
+            "OPENAI_API_KEY environment variable not set."
+        )
+
+    blog_topic = input("Enter the topic for the blog generation: ")
+
+    blog_generator = BlogGen(api_key, blog_topic)
+    blog_generator.TOPIC_SELECTION_SYSTEM_PROMPT = (
+        blog_generator.TOPIC_SELECTION_SYSTEM_PROMPT.replace(
+            "{{BLOG_TOPIC}}", blog_topic
+        )
+    )
+
+    blog_generator.run_workflow()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/playground/demos/ui_software_demo.py b/playground/demos/design_team/ui_software_demo.py
similarity index 100%
rename from playground/demos/ui_software_demo.py
rename to playground/demos/design_team/ui_software_demo.py
diff --git a/playground/demos/developer_swarm/main.py b/playground/demos/developer_swarm/main.py
new file mode 100644
index 00000000..18c0a346
--- /dev/null
+++ b/playground/demos/developer_swarm/main.py
@@ -0,0 +1,63 @@
+"""
+Swarm of developers that write documentation and tests for a given code snippet.
+
+This is a simple example of how to use the swarms library to create a swarm of developers that write documentation and tests for a given code snippet.
+
+The swarm is composed of two agents:
+    - Documentation agent: writes documentation for a given code snippet.
+    - Tests agent: writes tests for a given code snippet.
+    
+The swarm is initialized with a language model that is used by the agents to generate text. In this example, we use the OpenAI GPT-3 language model.
+
+Agent:
+Documentation agent -> Tests agent
+
+
+"""
+import os
+
+from dotenv import load_dotenv
+
+from swarms.models import OpenAIChat
+from swarms.prompts.programming import DOCUMENTATION_SOP, TEST_SOP
+from swarms.structs import Agent
+
+load_dotenv()
+api_key = os.getenv("OPENAI_API_KEY")
+
+
+TASK = """
+CODE
+
+"""
+
+# Initialize the language model
+llm = OpenAIChat(openai_api_key=api_key, max_tokens=5000)
+
+
+# Documentation agent
+documentation_agent = Agent(
+    llm=llm,
+    sop=DOCUMENTATION_SOP,
+    max_loops=1,
+)
+
+
+# Tests agent
+tests_agent = Agent(
+    llm=llm,
+    sop=TEST_SOP,
+    max_loops=2,
+)
+
+
+# Run the documentation agent
+documentation = documentation_agent.run(
+    f"Write documentation for the following code:{TASK}"
+)
+
+# Run the tests agent
+tests = tests_agent.run(
+    f"Write tests for the following code:{TASK} here is the"
+    f" documentation: {documentation}"
+)
diff --git a/playground/demos/education/education.py b/playground/demos/education/education.py
new file mode 100644
index 00000000..77f16f1b
--- /dev/null
+++ b/playground/demos/education/education.py
@@ -0,0 +1,76 @@
+import os
+from dotenv import load_dotenv
+from swarms.models import OpenAIChat
+from swarms.models.stable_diffusion import StableDiffusion
+from swarms.structs import Agent, SequentialWorkflow
+import swarms.prompts.education as edu_prompts
+
+# Load environment variables
+load_dotenv()
+api_key = os.getenv("OPENAI_API_KEY")
+stability_api_key = os.getenv("STABILITY_API_KEY")
+
+# Initialize language model
+llm = OpenAIChat(
+    openai_api_key=api_key, temperature=0.5, max_tokens=3000
+)
+
+# Initialize Stable Diffusion
+sd_api = StableDiffusion(api_key=stability_api_key)
+
+# User preferences (can be dynamically set in a real application)
+user_preferences = {
+    "subjects": "Cognitive Architectures",
+    "learning_style": "Visual",
+    "challenge_level": "Moderate",
+}
+
+# Formatted prompts from user preferences
+curriculum_prompt = edu_prompts.CURRICULUM_DESIGN_PROMPT.format(
+    **user_preferences
+)
+interactive_prompt = edu_prompts.INTERACTIVE_LEARNING_PROMPT.format(
+    **user_preferences
+)
+sample_prompt = edu_prompts.SAMPLE_TEST_PROMPT.format(
+    **user_preferences
+)
+image_prompt = edu_prompts.IMAGE_GENERATION_PROMPT.format(
+    **user_preferences
+)
+
+# Initialize agents for different educational tasks
+curriculum_agent = Agent(llm=llm, max_loops=1, sop=curriculum_prompt)
+interactive_learning_agent = Agent(
+    llm=llm, max_loops=1, sop=interactive_prompt
+)
+sample_lesson_agent = Agent(llm=llm, max_loops=1, sop=sample_prompt)
+
+# Create Sequential Workflow
+workflow = SequentialWorkflow(max_loops=1)
+
+# Add tasks to workflow with personalized prompts
+workflow.add(curriculum_agent, "Generate a curriculum")
+workflow.add(
+    interactive_learning_agent, "Generate an interactive lesson"
+)
+workflow.add(sample_lesson_agent, "Generate a practice test")
+
+# Execute the workflow for text-based tasks
+workflow.run()
+
+# Generate an image using Stable Diffusion
+image_result = sd_api.run(image_prompt)
+
+# Output results for each task
+for task in workflow.tasks:
+    print(
+        f"Task Description: {task.description}\nResult:"
+        f" {task.result}\n"
+    )
+
+# Output image result
+print(
+    "Image Generation Task: Generate an image for the interactive"
+    f" lesson\nResult: {image_result}"
+)
diff --git a/playground/demos/grupa/app.py b/playground/demos/grupa/app.py
new file mode 100644
index 00000000..3ab52e22
--- /dev/null
+++ b/playground/demos/grupa/app.py
@@ -0,0 +1,149 @@
+import os
+
+from dotenv import load_dotenv
+
+from swarms.models import OpenAIChat
+from swarms.prompts.code_interpreter import CODE_INTERPRETER
+from swarms.structs import Agent
+from swarms.prompts.programming import TEST_SOP, DOCUMENTATION_SOP
+from termcolor import colored
+
+load_dotenv()
+
+
+FEATURE = (
+    "Implement an all-new signup system in typescript using supabase"
+)
+
+CODEBASE = """
+import React, { useState } from 'react';
+import UpperPanel from './UpperPanel';
+import LowerPanel from './LowerPanel';
+
+const MainPanel = () => {
+  const [promptInstructionForLowerPanel, setPromptInstructionForLowerPanel] = useState('');  
+  const [formData, setFormData] = useState('');
+  const [isLoading, setIsLoading] = useState(false);  
+
+  return (
+    <div className="flex h-screen">
+      <UpperPanel setPromptInstructionForLowerPanel={setPromptInstructionForLowerPanel} 
+      isLoading={isLoading}
+      setIsLoading={setIsLoading}      
+      />
+      <LowerPanel promptInstruction={promptInstructionForLowerPanel} isLoading={isLoading} />
+    </div>
+  );
+};
+
+export default MainPanel;
+
+
+"""
+
+# Load the environment variables
+api_key = os.getenv("OPENAI_API_KEY")
+
+# Initialize the language agent
+llm = OpenAIChat(
+    model_name="gpt-4",
+    openai_api_key=api_key,
+    temperature=0.5,
+    max_tokens=4000,
+)
+
+# Product Manager Agent init
+product_manager_agent = Agent(
+    llm=llm, max_loops=1, sop=CODE_INTERPRETER, autosave=True
+)
+
+# Initialize the agent with the language agent
+feature_implementer_frontend = Agent(
+    llm=llm, max_loops=1, sop=CODE_INTERPRETER, autosave=True
+)
+
+# Create another agent for a different task
+feature_implementer_backend = Agent(
+    llm=llm, max_loops=1, sop=CODE_INTERPRETER, autosave=True
+)
+
+# Create another agent for a different task
+tester_agent = Agent(
+    llm=llm, max_loops=1, sop=TEST_SOP, autosave=True
+)
+
+# Create another agent for a different task
+documenting_agent = Agent(
+    llm=llm, max_loops=1, sop=DOCUMENTATION_SOP, autosave=True
+)
+
+
+# Product Agent prompt
+def feature_codebase_product_agentprompt(
+    feature: str, codebase: str
+) -> str:
+    prompt = (
+        "Create an algorithmic pseudocode for an all-new feature:"
+        f" {feature} based on this codebase: {codebase}"
+    )
+    return prompt
+
+
+# Product Manager Agent
+product_manager_out = product_manager_agent.run(
+    feature_codebase_product_agentprompt(FEATURE, CODEBASE)
+)
+print(
+    colored(
+        (
+            "---------------------------- Product Manager Plan:"
+            f" {product_manager_out}"
+        ),
+        "cyan",
+    )
+)
+
+# Feature Implementer  Agent
+agent1_out = feature_implementer_frontend.run(
+    f"Create the backend code for {FEATURE} in markdown based off of"
+    f" this algorithmic pseudocode: {product_manager_out} the logic"
+    f" based on the following codebase: {CODEBASE}"
+)
+print(
+    colored(
+        (
+            "--------------------- Feature Implementer Code logic:"
+            f" {agent1_out}"
+        ),
+        "cyan",
+    )
+)
+
+# Tester agent
+tester_agent_out = tester_agent.run(
+    f"Create tests for the following code: {agent1_out}"
+)
+print(
+    colored(
+        (
+            "---------------------------- Tests for the logic:"
+            f" {tester_agent_out}"
+        ),
+        "green",
+    )
+)
+
+
+# Documentation Agent
+documenter_agent_out = documenting_agent.run(
+    f"Document the following code: {agent1_out}"
+)
+print(
+    colored(
+        (
+            "---------------------------- Documentation for the"
+            f" logic: {documenter_agent_out}"
+        ),
+        "yellow",
+    )
+)
diff --git a/playground/demos/grupa/run__software_gpt.sh b/playground/demos/grupa/run__software_gpt.sh
new file mode 100755
index 00000000..7ae5b190
--- /dev/null
+++ b/playground/demos/grupa/run__software_gpt.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Define the base URL
+base_url="http://localhost:8000"
+
+# Define the JSON payload
+payload='{"feature": "login system", "codebase": "existing codebase here"}'
+
+# Send POST request
+echo "Sending request to /agent/ endpoint..."
+response=$(curl -s -X POST "$base_url/agent/" -H "Content-Type: application/json" -d "$payload")
+
+echo "Response: $response"
\ No newline at end of file
diff --git a/playground/demos/grupa/test_bash.bash b/playground/demos/grupa/test_bash.bash
new file mode 100755
index 00000000..7ae5b190
--- /dev/null
+++ b/playground/demos/grupa/test_bash.bash
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Define the base URL
+base_url="http://localhost:8000"
+
+# Define the JSON payload
+payload='{"feature": "login system", "codebase": "existing codebase here"}'
+
+# Send POST request
+echo "Sending request to /agent/ endpoint..."
+response=$(curl -s -X POST "$base_url/agent/" -H "Content-Type: application/json" -d "$payload")
+
+echo "Response: $response"
\ No newline at end of file
diff --git a/playground/demos/jarvis_multi_modal_auto_agent/jarvis.py b/playground/demos/jarvis_multi_modal_auto_agent/jarvis.py
new file mode 100644
index 00000000..05cd4fff
--- /dev/null
+++ b/playground/demos/jarvis_multi_modal_auto_agent/jarvis.py
@@ -0,0 +1,20 @@
+from swarms.structs import Agent
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.prompts.multi_modal_autonomous_instruction_prompt import (
+    MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
+)
+
+
+llm = GPT4VisionAPI()
+
+task = "What is the color of the object?"
+img = "images/swarms.jpeg"
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm,
+    sop=MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
+    max_loops="auto",
+)
+
+agent.run(task=task, img=img)
diff --git a/playground/demos/logistics/factory_image1.jpg b/playground/demos/logistics/factory_image1.jpg
new file mode 100644
index 00000000..8772e32d
Binary files /dev/null and b/playground/demos/logistics/factory_image1.jpg differ
diff --git a/playground/demos/logistics/logistics.py b/playground/demos/logistics/logistics.py
new file mode 100644
index 00000000..6a05d304
--- /dev/null
+++ b/playground/demos/logistics/logistics.py
@@ -0,0 +1,85 @@
+from swarms.structs import Agent
+import os
+from dotenv import load_dotenv
+from swarms.models import GPT4VisionAPI
+from swarms.prompts.logistics import (
+    Health_Security_Agent_Prompt,
+    Quality_Control_Agent_Prompt,
+    Productivity_Agent_Prompt,
+    Safety_Agent_Prompt,
+    Security_Agent_Prompt,
+    Sustainability_Agent_Prompt,
+    Efficiency_Agent_Prompt,
+)
+
+load_dotenv()
+api_key = os.getenv("OPENAI_API_KEY")
+
+llm = GPT4VisionAPI(openai_api_key=api_key)
+
+# Image for analysis
+factory_image = "factory_image1.jpg"
+
+# Initialize agents with respective prompts
+health_security_agent = Agent(
+    llm=llm,
+    sop=Health_Security_Agent_Prompt,
+    max_loops=3,
+    multi_modal=True,
+)
+quality_control_agent = Agent(
+    llm=llm,
+    sop=Quality_Control_Agent_Prompt,
+    max_loops=3,
+    multi_modal=True,
+)
+productivity_agent = Agent(
+    llm=llm,
+    sop=Productivity_Agent_Prompt,
+    max_loops=3,
+    multi_modal=True,
+)
+safety_agent = Agent(
+    llm=llm, sop=Safety_Agent_Prompt, max_loops=3, multi_modal=True
+)
+security_agent = Agent(
+    llm=llm, sop=Security_Agent_Prompt, max_loops=3, multi_modal=True
+)
+sustainability_agent = Agent(
+    llm=llm,
+    sop=Sustainability_Agent_Prompt,
+    max_loops=3,
+    multi_modal=True,
+)
+efficiency_agent = Agent(
+    llm=llm,
+    sop=Efficiency_Agent_Prompt,
+    max_loops=3,
+    multi_modal=True,
+)
+
+# Run agents with respective tasks on the same image
+health_analysis = health_security_agent.run(
+    "Analyze the safety of this factory", factory_image
+)
+quality_analysis = quality_control_agent.run(
+    "Examine product quality in the factory", factory_image
+)
+productivity_analysis = productivity_agent.run(
+    "Evaluate factory productivity", factory_image
+)
+safety_analysis = safety_agent.run(
+    "Inspect the factory's adherence to safety standards",
+    factory_image,
+)
+security_analysis = security_agent.run(
+    "Assess the factory's security measures and systems",
+    factory_image,
+)
+sustainability_analysis = sustainability_agent.run(
+    "Examine the factory's sustainability practices", factory_image
+)
+efficiency_analysis = efficiency_agent.run(
+    "Analyze the efficiency of the factory's manufacturing process",
+    factory_image,
+)
diff --git a/playground/demos/multi_modal_auto_agent.py b/playground/demos/multi_modal_auto_agent.py
deleted file mode 100644
index b462795f..00000000
--- a/playground/demos/multi_modal_auto_agent.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from swarms.structs import Flow
-from swarms.models import Idefics
-
-# Multi Modality Auto Agent
-llm = Idefics(max_length=2000)
-
-task = "User: What is in this image? https://upload.wikimedia.org/wikipedia/commons/8/86/Id%C3%A9fix.JPG"
-
-## Initialize the workflow
-flow = Flow(
-    llm=llm,
-    max_loops=2,
-    dashboard=True,
-    # stopping_condition=None,  # You can define a stopping condition as needed.
-    # loop_interval=1,
-    # retry_attempts=3,
-    # retry_interval=1,
-    # interactive=False,  # Set to 'True' for interactive mode.
-    # dynamic_temperature=False,  # Set to 'True' for dynamic temperature handling.
-)
-
-# out = flow.load_state("flow_state.json")
-# temp = flow.dynamic_temperature()
-# filter = flow.add_response_filter("Trump")
-out = flow.run(task)
-# out = flow.validate_response(out)
-# out = flow.analyze_feedback(out)
-# out = flow.print_history_and_memory()
-# # out = flow.save_state("flow_state.json")
-# print(out)
diff --git a/playground/demos/multi_modal_autonomous_agents/multi_modal_auto_agent.py b/playground/demos/multi_modal_autonomous_agents/multi_modal_auto_agent.py
new file mode 100644
index 00000000..74be8d5a
--- /dev/null
+++ b/playground/demos/multi_modal_autonomous_agents/multi_modal_auto_agent.py
@@ -0,0 +1,17 @@
+from swarms.structs import Agent
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+
+
+llm = GPT4VisionAPI()
+
+task = "What is the color of the object?"
+img = "images/swarms.jpeg"
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm,
+    max_loops="auto",
+    dashboard=True,
+)
+
+agent.run(task=task, img=img)
diff --git a/playground/demos/multimodal_tot/idea2img.py b/playground/demos/multimodal_tot/idea2img.py
new file mode 100644
index 00000000..4a6c1da3
--- /dev/null
+++ b/playground/demos/multimodal_tot/idea2img.py
@@ -0,0 +1,185 @@
+import datetime
+import os
+
+import streamlit as st
+from dotenv import load_dotenv
+
+from swarms.models import OpenAIChat
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.models.stable_diffusion import StableDiffusion
+from swarms.structs import Agent
+
+# Load environment variables
+load_dotenv()
+openai_api_key = os.getenv("OPENAI_API_KEY")
+stability_api_key = os.getenv("STABLE_API_KEY")
+
+# Initialize the models
+vision_api = GPT4VisionAPI(api_key=openai_api_key)
+sd_api = StableDiffusion(api_key=stability_api_key)
+gpt_api = OpenAIChat(openai_api_key=openai_api_key)
+
+
+class Idea2Image(Agent):
+    def __init__(self, llm, vision_api):
+        super().__init__(llm=llm)
+        self.vision_api = vision_api
+
+    def run(self, initial_prompt, num_iterations, run_folder):
+        current_prompt = initial_prompt
+
+        for i in range(num_iterations):
+            print(f"Iteration {i}: Image generation and analysis")
+
+            if i == 0:
+                current_prompt = self.enrich_prompt(current_prompt)
+                print(f"Enriched Prompt: {current_prompt}")
+
+            img = sd_api.generate_and_move_image(
+                current_prompt, i, run_folder
+            )
+            if not img:
+                print("Failed to generate image")
+                break
+            print(f"Generated image at: {img}")
+
+            analysis = (
+                self.vision_api.run(img, current_prompt)
+                if img
+                else None
+            )
+            if analysis:
+                current_prompt += (
+                    ". " + analysis[:500]
+                )  # Ensure the analysis is concise
+                print(f"Image Analysis: {analysis}")
+            else:
+                print(f"Failed to analyze image at: {img}")
+
+    def enrich_prompt(self, prompt):
+        enrichment_task = (
+            "Create a concise and effective image generation prompt"
+            " within 400 characters or less, based on Stable"
+            " Diffusion and Dalle best practices to help it create"
+            " much better images. Starting prompt:"
+            f" \n\n'{prompt}'\n\nImprove the prompt with any"
+            " applicable details or keywords by considering the"
+            " following aspects: \n1. Subject details (like actions,"
+            " emotions, environment) \n2. Artistic style (such as"
+            " surrealism, hyperrealism) \n3. Medium (digital"
+            " painting, oil on canvas) \n4. Color themes and"
+            " lighting (like warm colors, cinematic lighting) \n5."
+            " Composition and framing (close-up, wide-angle) \n6."
+            " Additional elements (like a specific type of"
+            " background, weather conditions) \n7. Any other"
+            " artistic or thematic details that can make the image"
+            " more vivid and compelling. Help the image generator"
+            " create better images by enriching the prompt."
+        )
+        llm_result = self.llm.generate([enrichment_task])
+        return (
+            llm_result.generations[0][0].text[:500]
+            if llm_result.generations
+            else None
+        )
+
+    def run_gradio(self, initial_prompt, num_iterations, run_folder):
+        results = []
+        current_prompt = initial_prompt
+
+        for i in range(num_iterations):
+            enriched_prompt = (
+                self.enrich_prompt(current_prompt)
+                if i == 0
+                else current_prompt
+            )
+            img_path = sd_api.generate_and_move_image(
+                enriched_prompt, i, run_folder
+            )
+            analysis = (
+                self.vision_api.run(img_path, enriched_prompt)
+                if img_path
+                else None
+            )
+
+            if analysis:
+                current_prompt += (
+                    ". " + analysis[:500]
+                )  # Ensuring the analysis is concise
+            results.append((enriched_prompt, img_path, analysis))
+
+        return results
+
+
+# print(
+#     colored("---------------------------------------- MultiModal Tree of Thought agents for Image Generation", "cyan", attrs=["bold"])
+# )
+# # User input and setup
+# user_prompt = input("Prompt for image generation: ")
+# num_iterations = int(
+#     input("Enter the number of iterations for image improvement: ")
+# )
+# run_folder = os.path.join(
+#     "runs", datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
+# )
+# os.makedirs(run_folder, exist_ok=True)
+
+# print(
+#     colored(
+#         f"---------------------------------- Running Multi-Modal Tree of thoughts agent with {num_iterations} iterations", "green"
+#     )
+# )
+# # Initialize and run the agent
+# idea2image_agent = Idea2Image(gpt_api, vision_api)
+# idea2image_agent.run(user_prompt, num_iterations, run_folder)
+
+# print("Idea space has been traversed.")
+
+
+# Load environment variables and initialize the models
+load_dotenv()
+openai_api_key = os.getenv("OPENAI_API_KEY")
+stability_api_key = os.getenv("STABLE_API_KEY")
+vision_api = GPT4VisionAPI(api_key=openai_api_key)
+sd_api = StableDiffusion(api_key=stability_api_key)
+gpt_api = OpenAIChat(openai_api_key=openai_api_key)
+
+# Define the modified Idea2Image class here
+
+# Streamlit UI layout
+st.title(
+    "Explore the infinite Multi-Modal Idea Space with Idea2Image"
+)
+user_prompt = st.text_input("Prompt for image generation:")
+num_iterations = st.number_input(
+    "Enter the number of iterations for image improvement:",
+    min_value=1,
+    step=1,
+)
+
+if st.button("Generate Image"):
+    run_folder = os.path.join(
+        "runs", datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
+    )
+    os.makedirs(run_folder, exist_ok=True)
+    idea2image_agent = Idea2Image(gpt_api, vision_api)
+
+    results = idea2image_agent.run_gradio(
+        user_prompt, num_iterations, run_folder
+    )
+
+    for i, (enriched_prompt, img_path, analysis) in enumerate(
+        results
+    ):
+        st.write(f"Iteration {i+1}:")
+        st.write("Enriched Prompt:", enriched_prompt)
+        if img_path:
+            st.image(img_path, caption="Generated Image")
+        else:
+            st.error("Failed to generate image")
+        if analysis:
+            st.write("Image Analysis:", analysis)
+
+    st.success("Idea space has been traversed.")
+
+# [Add any additional necessary code adjustments]
diff --git a/playground/demos/multimodal_tot/main.py b/playground/demos/multimodal_tot/main.py
new file mode 100644
index 00000000..2d5ed653
--- /dev/null
+++ b/playground/demos/multimodal_tot/main.py
@@ -0,0 +1,114 @@
+"""
+Multi Modal tree of thoughts that leverages the GPT-4 language model and the
+Stable Diffusion model to generate a multimodal output and evaluate the
+output based a metric from 0.0 to 1.0 and then run a search algorithm using DFS and BFS and return the best output.
+    
+    
+task: Generate an image of a swarm of bees -> Image generator -> GPT4V evaluates the img from 0.0 to 1.0 -> DFS/BFS -> return the best output
+
+
+- GPT4Vision will evaluate the image from 0.0 to 1.0 based on how likely it accomplishes the task
+- DFS/BFS will search for the best output based on the evaluation from GPT4Vision
+- The output will be a multimodal output that is a combination of the image and the text
+- The output will be evaluated by GPT4Vision
+- The prompt to the image generator will be optimized from the output of GPT4Vision and the search
+
+"""
+
+import os
+from dotenv import load_dotenv
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.models.stable_diffusion import StableDiffusion
+from termcolor import colored
+
+# Load the environment variables
+load_dotenv()
+
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
+stable_api_key = os.environ.get("STABLE_API_KEY")
+
+
+# Initialize the language model
+llm = GPT4VisionAPI(
+    openai_api_key=api_key,
+    max_tokens=500,
+)
+
+# IMG Generator
+img_generator = StableDiffusion(api_key=stable_api_key)
+
+
+# Initialize the language model
+task = "Garden of Eden futuristic city graphic art"
+
+
+def evaluate_img(llm, task: str, img: str):
+    EVAL_IMG = f"""
+    Evaluate the image: {img} on a scale from 0.0 to 1.0 based on how likely it accomplishes the task: {task}. Output nothing than the float representing the evaluated img.
+    """
+    out = llm.run(task=EVAL_IMG, img=img)
+    out = float(out)
+    return out
+
+
+def enrichment_prompt(starting_prompt: str, evaluated_img: str):
+    enrichment_task = (
+        "Create a concise and effective image generation prompt"
+        " within 400 characters or less, based on Stable Diffusion"
+        " and Dalle best practices. Starting prompt:"
+        f" \n\n'{starting_prompt}'\n\nImprove the prompt with any"
+        " applicable details or keywords by considering the"
+        " following aspects: \n1. Subject details (like actions,"
+        " emotions, environment) \n2. Artistic style (such as"
+        " surrealism, hyperrealism) \n3. Medium (digital painting,"
+        " oil on canvas) \n4. Color themes and lighting (like warm"
+        " colors, cinematic lighting) \n5. Composition and framing"
+        " (close-up, wide-angle) \n6. Additional elements (like a"
+        " specific type of background, weather conditions) \n7. Any"
+        " other artistic or thematic details that can make the image"
+        " more vivid and compelling. 8. Based on the evaluation of"
+        " the first generated prompt used by the first prompt:"
+        f" {evaluated_img} Enrich the prompt to generate a more"
+        " compelling image. Output only a new prompt to create a"
+        " better image"
+    )
+    return enrichment_task
+
+
+# Main loop
+max_iterations = 10  # Define the maximum number of iterations
+best_score = 0
+best_image = None
+
+for _ in range(max_iterations):
+    # Generate an image and get its path
+    print(colored(f"Generating img for Task: {task}", "purple"))
+
+    img_path = img_generator.run(
+        task=task
+    )  # This should return the file path of the generated image
+    img_path = img_path[0]
+    print(colored(f"Generated Image Path: {img_path}", "green"))
+
+    # Evaluate the image by passing the file path
+    score = evaluate_img(llm, task, img_path)
+    print(
+        colored(
+            f"Evaluated Image Score: {score} for {img_path}", "cyan"
+        )
+    )
+
+    # Update the best score and image path if necessary
+    if score > best_score:
+        best_score = score
+        best_image_path = img_path
+
+    # Enrich the prompt based on the evaluation
+    prompt = enrichment_prompt(task, score)
+    print(colored(f"Enrichment Prompt: {prompt}", "yellow"))
+
+
+# Output the best result
+print("Best Image Path:", best_image_path)
+print("Best Score:", best_score)
diff --git a/playground/demos/nutrition/full_fridge.jpg b/playground/demos/nutrition/full_fridge.jpg
new file mode 100644
index 00000000..c1b249c5
Binary files /dev/null and b/playground/demos/nutrition/full_fridge.jpg differ
diff --git a/playground/demos/nutrition/nutrition.py b/playground/demos/nutrition/nutrition.py
new file mode 100644
index 00000000..aca079ba
--- /dev/null
+++ b/playground/demos/nutrition/nutrition.py
@@ -0,0 +1,137 @@
+import os
+import base64
+import requests
+from dotenv import load_dotenv
+from swarms.models import Anthropic, OpenAIChat
+from swarms.structs import Agent
+
+# Load environment variables
+load_dotenv()
+openai_api_key = os.getenv("OPENAI_API_KEY")
+
+# Define prompts for various tasks
+MEAL_PLAN_PROMPT = (
+    "Based on the following user preferences: dietary restrictions as"
+    " vegetarian, preferred cuisines as Italian and Indian, a total"
+    " caloric intake of around 2000 calories per day, and an"
+    " exclusion of legumes, create a detailed weekly meal plan."
+    " Include a variety of meals for breakfast, lunch, dinner, and"
+    " optional snacks."
+)
+IMAGE_ANALYSIS_PROMPT = (
+    "Identify the items in this fridge, including their quantities"
+    " and condition."
+)
+
+
+# Function to encode image to base64
+def encode_image(image_path):
+    with open(image_path, "rb") as image_file:
+        return base64.b64encode(image_file.read()).decode("utf-8")
+
+
+# Initialize Language Model (LLM)
+llm = OpenAIChat(
+    openai_api_key=openai_api_key,
+    max_tokens=3000,
+)
+
+
+# Function to handle vision tasks
+def create_vision_agent(image_path):
+    base64_image = encode_image(image_path)
+    headers = {
+        "Content-Type": "application/json",
+        "Authorization": f"Bearer {openai_api_key}",
+    }
+    payload = {
+        "model": "gpt-4-vision-preview",
+        "messages": [
+            {
+                "role": "user",
+                "content": [
+                    {"type": "text", "text": IMAGE_ANALYSIS_PROMPT},
+                    {
+                        "type": "image_url",
+                        "image_url": {
+                            "url": f"data:image/jpeg;base64,{base64_image}"
+                        },
+                    },
+                ],
+            }
+        ],
+        "max_tokens": 300,
+    }
+    response = requests.post(
+        "https://api.openai.com/v1/chat/completions",
+        headers=headers,
+        json=payload,
+    )
+    return response.json()
+
+
+# Function to generate an integrated shopping list considering meal plan and fridge contents
+def generate_integrated_shopping_list(
+    meal_plan_output, image_analysis, user_preferences
+):
+    # Prepare the prompt for the LLM
+    fridge_contents = image_analysis["choices"][0]["message"][
+        "content"
+    ]
+    prompt = (
+        f"Based on this meal plan: {meal_plan_output}, and the"
+        f" following items in the fridge: {fridge_contents},"
+        " considering dietary preferences as vegetarian with a"
+        " preference for Italian and Indian cuisines, generate a"
+        " comprehensive shopping list that includes only the items"
+        " needed."
+    )
+
+    # Send the prompt to the LLM and return the response
+    response = llm(prompt)
+    return response  # assuming the response is a string
+
+
+# Define agent for meal planning
+meal_plan_agent = Agent(
+    llm=llm,
+    sop=MEAL_PLAN_PROMPT,
+    max_loops=1,
+    autosave=True,
+    saved_state_path="meal_plan_agent.json",
+)
+
+# User preferences for meal planning
+user_preferences = {
+    "dietary_restrictions": "vegetarian",
+    "preferred_cuisines": ["Italian", "Indian"],
+    "caloric_intake": 2000,
+    "other notes": "Doesn't eat legumes",
+}
+
+# Generate Meal Plan
+meal_plan_output = meal_plan_agent.run(
+    f"Generate a meal plan: {user_preferences}"
+)
+
+# Vision Agent - Analyze an Image
+image_analysis_output = create_vision_agent("full_fridge.jpg")
+
+# Generate Integrated Shopping List
+integrated_shopping_list = generate_integrated_shopping_list(
+    meal_plan_output, image_analysis_output, user_preferences
+)
+
+# Print and save the outputs
+print("Meal Plan:", meal_plan_output)
+print("Integrated Shopping List:", integrated_shopping_list)
+
+with open("nutrition_output.txt", "w") as file:
+    file.write("Meal Plan:\n" + meal_plan_output + "\n\n")
+    file.write(
+        "Integrated Shopping List:\n"
+        + integrated_shopping_list
+        + "\n"
+    )
+
+print("Outputs have been saved to nutrition_output.txt")
diff --git a/playground/demos/positive_med.py b/playground/demos/positive_med/positive_med.py
similarity index 75%
rename from playground/demos/positive_med.py
rename to playground/demos/positive_med/positive_med.py
index 6f7a2d3a..b92b9586 100644
--- a/playground/demos/positive_med.py
+++ b/playground/demos/positive_med/positive_med.py
@@ -1,5 +1,5 @@
 """
-Swarm Flow
+Swarm Agent
 Topic selection agent -> draft agent -> review agent -> distribution agent
 
 Topic Selection Agent:
@@ -15,42 +15,49 @@ Distribution Agent:
 - Social Media posts for the article.
 
 # TODO
+- Make prompts better
 - Add shorter and better topic generator prompt
 - Optimize writer prompt to create longer and more enjoyeable blogs
 - Use Local Models like Storywriter
 """
+import os
+
 from termcolor import colored
+
 from swarms.models import OpenAIChat
-from swarms.prompts.autoblogen import (
+from swarms.prompts.autobloggen import (
+    AUTOBLOG_REVIEW_PROMPT,
     DRAFT_AGENT_SYSTEM_PROMPT,
-    REVIEW_PROMPT,
     SOCIAL_MEDIA_SYSTEM_PROMPT_AGENT,
-    TOPIC_GENERATOR,
+    TOPIC_GENERATOR_SYSTEM_PROMPT,
 )
-import os
 
 api_key = os.environ["OPENAI_API_KEY"]
 llm = OpenAIChat(openai_api_key=api_key)
 
 
 def get_review_prompt(article):
-    prompt = REVIEW_PROMPT.replace("{{ARTICLE}}", article)
+    prompt = AUTOBLOG_REVIEW_PROMPT.replace("{{ARTICLE}}", article)
     return prompt
 
 
-def social_media_prompt(article: str, goal: str = "Clicks and engagement"):
-    prompt = SOCIAL_MEDIA_SYSTEM_PROMPT_AGENT.replace("{{ARTICLE}}", article).replace(
-        "{{GOAL}}", goal
-    )
+def social_media_prompt(
+    article: str, goal: str = "Clicks and engagement"
+):
+    prompt = SOCIAL_MEDIA_SYSTEM_PROMPT_AGENT.replace(
+        "{{ARTICLE}}", article
+    ).replace("{{GOAL}}", goal)
     return prompt
 
 
 # Agent that generates topics
 topic_selection_task = (
-    "Generate 10 topics on gaining mental clarity using ancient practices"
+    "Generate 10 topics on gaining mental clarity using ancient"
+    " practices"
 )
 topics = llm(
-    f"Your System Instructions: {TOPIC_GENERATOR}, Your current task: {topic_selection_task}"
+    f"Your System Instructions: {TOPIC_GENERATOR_SYSTEM_PROMPT}, Your"
+    f" current task: {topic_selection_task}"
 )
 
 dashboard = print(
@@ -109,7 +116,9 @@ reviewed_draft = print(
 
 
 # Agent that publishes on social media
-distribution_agent = llm(social_media_prompt(draft_blog, goal="Clicks and engagement"))
+distribution_agent = llm(
+    social_media_prompt(draft_blog, goal="Clicks and engagement")
+)
 distribution_agent_out = print(
     colored(
         f"""
diff --git a/playground/demos/swarm_of_mma_manufacturing/assembly_line.jpg b/playground/demos/swarm_of_mma_manufacturing/assembly_line.jpg
new file mode 100644
index 00000000..5e9a0fff
Binary files /dev/null and b/playground/demos/swarm_of_mma_manufacturing/assembly_line.jpg differ
diff --git a/playground/demos/swarm_of_mma_manufacturing/main.py b/playground/demos/swarm_of_mma_manufacturing/main.py
new file mode 100644
index 00000000..05b0e8e5
--- /dev/null
+++ b/playground/demos/swarm_of_mma_manufacturing/main.py
@@ -0,0 +1,157 @@
+"""
+Swarm of multi modal autonomous agents for manufacturing!
+---------------------------------------------------------    
+Health Security agent: Agent that monitors the health of working conditions: input image of factory output: health safety index 0.0 - 1.0 being the highest
+Quality Control agent: Agent that monitors the quality of the product: input image of product output: quality index 0.0 - 1.0 being the highest
+Productivity agent: Agent that monitors the productivity of the factory: input image of factory output: productivity index 0.0 - 1.0 being the highest
+Safety agent: Agent that monitors the safety of the factory: input image of factory output: safety index 0.0 - 1.0 being the highest
+Security agent: Agent that monitors the security of the factory: input image of factory output: security index 0.0 - 1.0 being the highest
+Sustainability agent: Agent that monitors the sustainability of the factory: input image of factory output: sustainability index 0.0 - 1.0 being the highest
+Efficiency agent: Agent that monitors the efficiency of the factory: input image of factory output: efficiency index 0.0 - 1.0 being the highest    
+
+
+Agent:
+health security agent -> quality control agent -> productivity agent -> safety agent -> security agent -> sustainability agent -> efficiency agent 
+"""
+import os
+
+from dotenv import load_dotenv
+from termcolor import colored
+
+from swarms.models import GPT4VisionAPI
+from swarms.structs import Agent
+
+load_dotenv()
+api_key = os.getenv("OPENAI_API_KEY")
+
+# GPT4VisionAPI
+llm = GPT4VisionAPI(openai_api_key=api_key, max_tokens=2000)
+
+assembly_line = (
+    "playground/demos/swarm_of_mma_manufacturing/assembly_line.jpg"
+)
+red_robots = (
+    "playground/demos/swarm_of_mma_manufacturing/red_robots.jpg"
+)
+robots = "playground/demos/swarm_of_mma_manufacturing/robots.jpg"
+tesla_assembly_line = (
+    "playground/demos/swarm_of_mma_manufacturing/tesla_assembly.jpg"
+)
+
+
+# Define detailed prompts for each agent
+tasks = {
+    "health_safety": (
+        "Analyze the factory's working environment for health safety."
+        " Focus on cleanliness, ventilation, spacing between"
+        " workstations, and personal protective equipment"
+        " availability."
+    ),
+    "productivity": (
+        "Review the factory's workflow efficiency, machine"
+        " utilization, and employee engagement. Identify operational"
+        " delays or bottlenecks."
+    ),
+    "safety": (
+        "Analyze the factory's safety measures, including fire exits,"
+        " safety signage, and emergency response equipment."
+    ),
+    "security": (
+        "Evaluate the factory's security systems, entry/exit"
+        " controls, and potential vulnerabilities."
+    ),
+    "sustainability": (
+        "Inspect the factory's sustainability practices, including"
+        " waste management, energy usage, and eco-friendly processes."
+    ),
+    "efficiency": (
+        "Assess the manufacturing process's efficiency, considering"
+        " the layout, logistics, and automation level."
+    ),
+}
+
+
+# Define prompts for each agent
+health_safety_prompt = tasks["health_safety"]
+productivity_prompt = tasks["productivity"]
+safety_prompt = tasks["safety"]
+security_prompt = tasks["security"]
+sustainability_prompt = tasks["sustainability"]
+efficiency_prompt = tasks["efficiency"]
+
+
+# Health security agent
+health_security_agent = Agent(
+    llm=llm,
+    sop_list=health_safety_prompt,
+    max_loops=1,
+    multi_modal=True,
+)
+
+# Quality control agent
+productivity_check_agent = Agent(
+    llm=llm,
+    sop=productivity_prompt,
+    max_loops=1,
+    multi_modal=True,
+    autosave=True,
+)
+
+# Security agent
+security_check_agent = Agent(
+    llm=llm,
+    sop=security_prompt,
+    max_loops=1,
+    multi_modal=True,
+    autosave=True,
+)
+
+# Efficiency agent
+efficiency_check_agent = Agent(
+    llm=llm,
+    sop=efficiency_prompt,
+    max_loops=1,
+    multi_modal=True,
+    autosave=True,
+)
+
+print(colored("Running the agents...", "green"))
+
+
+print(colored("Running health check agent initializing...", "cyan"))
+# Add the first task to the health_security_agent
+health_check = health_security_agent.run(
+    "Analyze the safety of this factory", robots
+)
+
+
+print(
+    colored(
+        "--------------- Productivity agents initializing...", "green"
+    )
+)
+# Add the third task to the productivity_check_agent
+productivity_check = productivity_check_agent.run(
+    health_check, assembly_line
+)
+
+print(
+    colored(
+        "--------------- Security agents initializing...", "green"
+    )
+)
+# Add the fourth task to the security_check_agent
+security_check = security_check_agent.run(
+    productivity_check, red_robots
+)
+
+
+print(
+    colored(
+        "--------------- Efficiency agents initializing...", "cyan"
+    )
+)
+# Add the fifth task to the efficiency_check_agent
+efficiency_check = efficiency_check_agent.run(
+    security_check, tesla_assembly_line
+)
diff --git a/playground/demos/swarm_of_mma_manufacturing/red_robots.jpg b/playground/demos/swarm_of_mma_manufacturing/red_robots.jpg
new file mode 100644
index 00000000..f086fa67
Binary files /dev/null and b/playground/demos/swarm_of_mma_manufacturing/red_robots.jpg differ
diff --git a/playground/demos/swarm_of_mma_manufacturing/robots.jpg b/playground/demos/swarm_of_mma_manufacturing/robots.jpg
new file mode 100644
index 00000000..bddab6e4
Binary files /dev/null and b/playground/demos/swarm_of_mma_manufacturing/robots.jpg differ
diff --git a/playground/demos/swarm_of_mma_manufacturing/tesla_assembly.jpg b/playground/demos/swarm_of_mma_manufacturing/tesla_assembly.jpg
new file mode 100644
index 00000000..00456f61
Binary files /dev/null and b/playground/demos/swarm_of_mma_manufacturing/tesla_assembly.jpg differ
diff --git a/playground/demos/urban_planning/urban_area.jpg b/playground/demos/urban_planning/urban_area.jpg
new file mode 100644
index 00000000..7eca028c
Binary files /dev/null and b/playground/demos/urban_planning/urban_area.jpg differ
diff --git a/playground/demos/urban_planning/urban_planning.py b/playground/demos/urban_planning/urban_planning.py
new file mode 100644
index 00000000..e85b4d31
--- /dev/null
+++ b/playground/demos/urban_planning/urban_planning.py
@@ -0,0 +1,84 @@
+import os
+from dotenv import load_dotenv
+from swarms.models import OpenAIChat, GPT4VisionAPI
+from swarms.structs import Agent, SequentialWorkflow
+import swarms.prompts.urban_planning as upp
+
+# Load environment variables
+load_dotenv()
+api_key = os.getenv("OPENAI_API_KEY")
+stability_api_key = os.getenv("STABILITY_API_KEY")
+
+# Initialize language model
+llm = OpenAIChat(
+    openai_api_key=api_key, temperature=0.5, max_tokens=3000
+)
+
+# Initialize Vision model
+vision_api = GPT4VisionAPI(api_key=api_key)
+
+# Initialize agents for urban planning tasks
+architecture_analysis_agent = Agent(
+    llm=llm, max_loops=1, sop=upp.ARCHITECTURE_ANALYSIS_PROMPT
+)
+infrastructure_evaluation_agent = Agent(
+    llm=llm, max_loops=1, sop=upp.INFRASTRUCTURE_EVALUATION_PROMPT
+)
+traffic_flow_analysis_agent = Agent(
+    llm=llm, max_loops=1, sop=upp.TRAFFIC_FLOW_ANALYSIS_PROMPT
+)
+environmental_impact_assessment_agent = Agent(
+    llm=llm,
+    max_loops=1,
+    sop=upp.ENVIRONMENTAL_IMPACT_ASSESSMENT_PROMPT,
+)
+public_space_utilization_agent = Agent(
+    llm=llm, max_loops=1, sop=upp.PUBLIC_SPACE_UTILIZATION_PROMPT
+)
+socioeconomic_impact_analysis_agent = Agent(
+    llm=llm, max_loops=1, sop=upp.SOCIOECONOMIC_IMPACT_ANALYSIS_PROMPT
+)
+
+# Initialize the final planning agent
+final_plan_agent = Agent(
+    llm=llm, max_loops=1, sop=upp.FINAL_URBAN_IMPROVEMENT_PLAN_PROMPT
+)
+
+# Create Sequential Workflow
+workflow = SequentialWorkflow(max_loops=1)
+
+# Add tasks to workflow with personalized prompts
+workflow.add(architecture_analysis_agent, "Architecture Analysis")
+workflow.add(
+    infrastructure_evaluation_agent, "Infrastructure Evaluation"
+)
+workflow.add(traffic_flow_analysis_agent, "Traffic Flow Analysis")
+workflow.add(
+    environmental_impact_assessment_agent,
+    "Environmental Impact Assessment",
+)
+workflow.add(
+    public_space_utilization_agent, "Public Space Utilization"
+)
+workflow.add(
+    socioeconomic_impact_analysis_agent,
+    "Socioeconomic Impact Analysis",
+)
+workflow.add(
+    final_plan_agent,
+    (
+        "Generate the final urban improvement plan based on all"
+        " previous agent's findings"
+    ),
+)
+# Run the workflow for individual analysis tasks
+
+# Execute the workflow for the final planning
+workflow.run()
+
+# Output results for each task and the final plan
+for task in workflow.tasks:
+    print(
+        f"Task Description: {task.description}\nResult:"
+        f" {task.result}\n"
+    )
diff --git a/playground/demos/xray/xray.py b/playground/demos/xray/xray.py
new file mode 100644
index 00000000..20e89e6d
--- /dev/null
+++ b/playground/demos/xray/xray.py
@@ -0,0 +1,73 @@
+import os
+
+from dotenv import load_dotenv
+
+from swarms.models import GPT4VisionAPI, OpenAIChat
+from swarms.prompts.xray_swarm_prompt import (
+    TREATMENT_PLAN_PROMPT,
+    XRAY_ANALYSIS_PROMPT,
+)
+from swarms.structs.agent import Agent
+
+# Load environment variables
+load_dotenv()
+openai_api_key = os.getenv("OPENAI_API_KEY")
+
+# Function to analyze an X-ray image
+multimodal_llm = GPT4VisionAPI(
+    openai_api_key=openai_api_key,
+)
+
+# Initialize Language Model (LLM)
+llm = OpenAIChat(
+    openai_api_key=openai_api_key,
+    max_tokens=3000,
+)
+
+
+# Function to analyze an X-ray image
+analyze_xray_agent = Agent(
+    llm=multimodal_llm,
+    autosave=True,
+    sop=XRAY_ANALYSIS_PROMPT,
+    multi_modal=True,
+)
+
+
+# Treatment Plan Agent
+treatment_agent = Agent(
+    llm=multimodal_llm,
+    autosave=True,
+    sop=TREATMENT_PLAN_PROMPT,
+    max_loops=4,
+)
+
+
+# Function to generate a treatment plan
+def generate_treatment_plan(diagnosis):
+    treatment_plan_prompt = TREATMENT_PLAN_PROMPT.format(diagnosis)
+    # Using the llm object with the 'prompt' argument
+    return treatment_agent.run(treatment_plan_prompt)
+
+
+# X-ray Agent - Analyze an X-ray image
+xray_image_path = "playground/demos/xray/xray2.jpg"
+
+
+# Diagnosis
+diagnosis = analyze_xray_agent.run(
+    task="Analyze the following XRAY", img=xray_image_path
+)
+
+# Generate Treatment Plan
+treatment_plan_output = generate_treatment_plan(diagnosis)
+
+# Print and save the outputs
+print("X-ray Analysis:", diagnosis)
+print("Treatment Plan:", treatment_plan_output)
+
+with open("medical_analysis_output.txt", "w") as file:
+    file.write("X-ray Analysis:\n" + diagnosis + "\n\n")
+    file.write("Treatment Plan:\n" + treatment_plan_output + "\n")
+
+print("Outputs have been saved to medical_analysis_output.txt")
diff --git a/playground/demos/xray/xray2.jpg b/playground/demos/xray/xray2.jpg
new file mode 100644
index 00000000..6553cd41
Binary files /dev/null and b/playground/demos/xray/xray2.jpg differ
diff --git a/playground/memory/qdrant/usage.py b/playground/memory/qdrant/usage.py
new file mode 100644
index 00000000..2b7c4a8e
--- /dev/null
+++ b/playground/memory/qdrant/usage.py
@@ -0,0 +1,25 @@
+from langchain.document_loaders import CSVLoader
+from swarms.memory import qdrant
+
+loader = CSVLoader(
+    file_path="../document_parsing/aipg/aipg.csv",
+    encoding="utf-8-sig",
+)
+docs = loader.load()
+
+
+# Initialize the Qdrant instance
+# See qdrant documentation on how to run locally
+qdrant_client = qdrant.Qdrant(
+    host="https://697ea26c-2881-4e17-8af4-817fcb5862e8.europe-west3-0.gcp.cloud.qdrant.io",
+    collection_name="qdrant",
+    api_key="BhG2_yINqNU-aKovSEBadn69Zszhbo5uaqdJ6G_qDkdySjAljvuPqQ",
+)
+qdrant_client.add_vectors(docs)
+
+# Perform a search
+search_query = "Who is jojo"
+search_results = qdrant_client.search_vectors(search_query)
+print("Search Results:")
+for result in search_results:
+    print(result)
diff --git a/playground/models/bingchat.py b/playground/models/bingchat.py
index bf06ecc6..2af8472c 100644
--- a/playground/models/bingchat.py
+++ b/playground/models/bingchat.py
@@ -24,7 +24,9 @@ llm = OpenAIChat(
 )
 
 # Initialize the Worker with the custom tool
-worker = Worker(llm=llm, ai_name="EdgeGPT Worker", external_tools=[edgegpt])
+worker = Worker(
+    llm=llm, ai_name="EdgeGPT Worker", external_tools=[edgegpt]
+)
 
 # Use the worker to process a task
 task = "Hello, my name is ChatGPT"
diff --git a/playground/models/bioclip.py b/playground/models/bioclip.py
index dcdd309b..307cf798 100644
--- a/playground/models/bioclip.py
+++ b/playground/models/bioclip.py
@@ -1,6 +1,8 @@
 from swarms.models.bioclip import BioClip
 
-clip = BioClip("hf-hub:microsoft/BiomedCLIP-PubMedBERT_256-vit_base_patch16_224")
+clip = BioClip(
+    "hf-hub:microsoft/BiomedCLIP-PubMedBERT_256-vit_base_patch16_224"
+)
 
 labels = [
     "adenocarcinoma histopathology",
@@ -15,5 +17,8 @@ labels = [
 ]
 
 result = clip("swarms.jpeg", labels)
-metadata = {"filename": "images/.jpg".split("/")[-1], "top_probs": result}
+metadata = {
+    "filename": "images/.jpg".split("/")[-1],
+    "top_probs": result,
+}
 clip.plot_image_with_metadata("swarms.jpeg", metadata)
diff --git a/playground/models/distilled_whiserpx.py b/playground/models/distilled_whiserpx.py
index 71e1d5ef..0742a1bc 100644
--- a/playground/models/distilled_whiserpx.py
+++ b/playground/models/distilled_whiserpx.py
@@ -7,4 +7,6 @@ model_wrapper = DistilWhisperModel()
 transcription = model_wrapper("path/to/audio.mp3")
 
 # For async usage
-transcription = asyncio.run(model_wrapper.async_transcribe("path/to/audio.mp3"))
+transcription = asyncio.run(
+    model_wrapper.async_transcribe("path/to/audio.mp3")
+)
diff --git a/playground/models/idefics.py b/playground/models/idefics.py
index 032e0f3b..39d6f4eb 100644
--- a/playground/models/idefics.py
+++ b/playground/models/idefics.py
@@ -2,11 +2,17 @@ from swarms.models import idefics
 
 model = idefics()
 
-user_input = "User: What is in this image? https://upload.wikimedia.org/wikipedia/commons/8/86/Id%C3%A9fix.JPG"
+user_input = (
+    "User: What is in this image?"
+    " https://upload.wikimedia.org/wikipedia/commons/8/86/Id%C3%A9fix.JPG"
+)
 response = model.chat(user_input)
 print(response)
 
-user_input = "User: And who is that? https://static.wikia.nocookie.net/asterix/images/2/25/R22b.gif/revision/latest?cb=20110815073052"
+user_input = (
+    "User: And who is that?"
+    " https://static.wikia.nocookie.net/asterix/images/2/25/R22b.gif/revision/latest?cb=20110815073052"
+)
 response = model.chat(user_input)
 print(response)
 
diff --git a/playground/models/llama_function_caller.py b/playground/models/llama_function_caller.py
index 43bca3a5..201009a8 100644
--- a/playground/models/llama_function_caller.py
+++ b/playground/models/llama_function_caller.py
@@ -28,7 +28,9 @@ llama_caller.add_func(
 )
 
 # Call the function
-result = llama_caller.call_function("get_weather", location="Paris", format="Celsius")
+result = llama_caller.call_function(
+    "get_weather", location="Paris", format="Celsius"
+)
 print(result)
 
 # Stream a user prompt
diff --git a/playground/models/mpt.py b/playground/models/mpt.py
index bdba8754..8ffa30db 100644
--- a/playground/models/mpt.py
+++ b/playground/models/mpt.py
@@ -1,7 +1,9 @@
 from swarms.models.mpt import MPT
 
 mpt_instance = MPT(
-    "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+    "mosaicml/mpt-7b-storywriter",
+    "EleutherAI/gpt-neox-20b",
+    max_tokens=150,
 )
 
 mpt_instance.generate("Once upon a time in a land far, far away...")
diff --git a/playground/models/nougat.py b/playground/models/nougat.py
index 198fee38..97e1f1a3 100644
--- a/playground/models/nougat.py
+++ b/playground/models/nougat.py
@@ -2,4 +2,4 @@ from swarms.models.nougat import Nougat
 
 nougat = Nougat()
 
-out = nougat("path/to/image.png")
+out = nougat("large.png")
diff --git a/playground/models/vilt.py b/playground/models/vilt.py
index 127514e0..8e40f59d 100644
--- a/playground/models/vilt.py
+++ b/playground/models/vilt.py
@@ -3,5 +3,6 @@ from swarms.models.vilt import Vilt
 model = Vilt()
 
 output = model(
-    "What is this image", "http://images.cocodataset.org/val2017/000000039769.jpg"
+    "What is this image",
+    "http://images.cocodataset.org/val2017/000000039769.jpg",
 )
diff --git a/playground/structs/agent_with_tools.py b/playground/structs/agent_with_tools.py
new file mode 100644
index 00000000..99f21638
--- /dev/null
+++ b/playground/structs/agent_with_tools.py
@@ -0,0 +1,77 @@
+"""
+    
+    
+tool decorated func [search_api] -> agent which parses the docs of the tool func 
+-> injected into prompt -> agent will output json containing tool usage -> agent output will be parsed -> tool executed
+-> terminal response can be returned to agent for self-healing
+    
+    
+"""
+
+import os
+
+from dotenv import load_dotenv
+
+# Import the OpenAIChat model and the Agent struct
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
+from swarms.tools.tool import tool
+
+# Load the environment variables
+load_dotenv()
+
+
+# Define a tool
+@tool
+def search_api(query: str, description: str):
+    """Search the web for the query
+
+    Args:
+        query (str): _description_
+
+    Returns:
+        _type_: _description_
+    """
+    return f"Search results for {query}"
+
+
+@tool
+def weather_api(
+    query: str,
+):
+    """_summary_
+
+    Args:
+        query (str): _description_
+    """
+    print(f"Getting the weather for {query}")
+
+
+@tool
+def rapid_api(query: str):
+    """_summary_
+
+    Args:
+        query (str): _description_
+    """
+    print(f"Getting the weather for {query}")
+
+
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
+
+# Initialize the language model
+llm = OpenAIChat(
+    temperature=0.5,
+    openai_api_key=api_key,
+)
+
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm, max_loops=1, dashboard=True, tools=[search_api]
+)
+
+# Run the workflow on a task
+out = agent.run("Generate a 10,000 word blog on health and wellness.")
+print(out)
diff --git a/playground/structs/autoscaler.py b/playground/structs/autoscaler.py
new file mode 100644
index 00000000..8b808db6
--- /dev/null
+++ b/playground/structs/autoscaler.py
@@ -0,0 +1,46 @@
+import os
+
+from dotenv import load_dotenv
+
+# Import the OpenAIChat model and the Agent struct
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
+from swarms.structs.autoscaler import AutoScaler
+
+
+# Load the environment variables
+load_dotenv()
+
+# Get the API key from the environment
+api_key = os.environ.get("OPENAI_API_KEY")
+
+# Initialize the language model
+llm = OpenAIChat(
+    temperature=0.5,
+    openai_api_key=api_key,
+)
+
+
+## Initialize the workflow
+agent = Agent(llm=llm, max_loops=1, dashboard=True)
+
+
+# Load the autoscaler
+autoscaler = AutoScaler(
+    initial_agents=2,
+    scale_up_factor=1,
+    idle_threshold=0.2,
+    busy_threshold=0.7,
+    agents=[agent],
+    autoscale=True,
+    min_agents=1,
+    max_agents=5,
+    custom_scale_strategy=None,
+)
+print(autoscaler)
+
+# Run the workflow on a task
+out = autoscaler.run(
+    agent.id, "Generate a 10,000 word blog on health and wellness."
+)
+print(out)
diff --git a/playground/structs/flow.py b/playground/structs/flow.py
index 8e34cce3..8ff45802 100644
--- a/playground/structs/flow.py
+++ b/playground/structs/flow.py
@@ -1,5 +1,5 @@
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 
 api_key = ""
 
@@ -12,7 +12,7 @@ llm = OpenAIChat(
 )
 
 ## Initialize the workflow
-flow = Flow(
+agent = Agent(
     llm=llm,
     max_loops=2,
     dashboard=True,
@@ -24,12 +24,12 @@ flow = Flow(
     # dynamic_temperature=False,  # Set to 'True' for dynamic temperature handling.
 )
 
-# out = flow.load_state("flow_state.json")
-# temp = flow.dynamic_temperature()
-# filter = flow.add_response_filter("Trump")
-out = flow.run("Generate a 10,000 word blog on health and wellness.")
-# out = flow.validate_response(out)
-# out = flow.analyze_feedback(out)
-# out = flow.print_history_and_memory()
-# # out = flow.save_state("flow_state.json")
+# out = agent.load_state("flow_state.json")
+# temp = agent.dynamic_temperature()
+# filter = agent.add_response_filter("Trump")
+out = agent.run("Generate a 10,000 word blog on health and wellness.")
+# out = agent.validate_response(out)
+# out = agent.analyze_feedback(out)
+# out = agent.print_history_and_memory()
+# # out = agent.save_state("flow_state.json")
 # print(out)
diff --git a/playground/structs/flow_tools.py b/playground/structs/flow_tools.py
deleted file mode 100644
index 647f6617..00000000
--- a/playground/structs/flow_tools.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from swarms.models import Anthropic
-from swarms.structs import Flow
-from swarms.tools.tool import tool
-
-import asyncio
-
-
-llm = Anthropic(
-    anthropic_api_key="",
-)
-
-
-async def async_load_playwright(url: str) -> str:
-    """Load the specified URLs using Playwright and parse using BeautifulSoup."""
-    from bs4 import BeautifulSoup
-    from playwright.async_api import async_playwright
-
-    results = ""
-    async with async_playwright() as p:
-        browser = await p.chromium.launch(headless=True)
-        try:
-            page = await browser.new_page()
-            await page.goto(url)
-
-            page_source = await page.content()
-            soup = BeautifulSoup(page_source, "html.parser")
-
-            for script in soup(["script", "style"]):
-                script.extract()
-
-            text = soup.get_text()
-            lines = (line.strip() for line in text.splitlines())
-            chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
-            results = "\n".join(chunk for chunk in chunks if chunk)
-        except Exception as e:
-            results = f"Error: {e}"
-        await browser.close()
-    return results
-
-
-def run_async(coro):
-    event_loop = asyncio.get_event_loop()
-    return event_loop.run_until_complete(coro)
-
-
-@tool
-def browse_web_page(url: str) -> str:
-    """Verbose way to scrape a whole webpage. Likely to cause issues parsing."""
-    return run_async(async_load_playwright(url))
-
-
-## Initialize the workflow
-flow = Flow(
-    llm=llm,
-    max_loops=5,
-    tools=[browse_web_page],
-    dashboard=True,
-)
-
-out = flow.run(
-    "Generate a 10,000 word blog on mental clarity and the benefits of meditation."
-)
diff --git a/playground/structs/fuyu_flow.py b/playground/structs/fuyu_flow.py
index 6f4dca5f..4231d827 100644
--- a/playground/structs/fuyu_flow.py
+++ b/playground/structs/fuyu_flow.py
@@ -1,10 +1,10 @@
-from swarms import Flow, Fuyu
+from swarms import Agent, Fuyu
 
 llm = Fuyu()
 
-flow = Flow(max_loops="auto", llm=llm)
+agent = Agent(max_loops="auto", llm=llm)
 
-flow.run(
+agent.run(
     task="Describe this image in a few sentences: ",
     img="https://unsplash.com/photos/0pIC5ByPpZY",
 )
diff --git a/playground/structs/multi_modal_flow.py b/playground/structs/multi_modal_flow.py
index d746d98f..b29c8bfd 100644
--- a/playground/structs/multi_modal_flow.py
+++ b/playground/structs/multi_modal_flow.py
@@ -1,14 +1,14 @@
 # This might not work in the beginning but it's a starting point
-from swarms.structs import Flow, GPT4V
+from swarms.structs import Agent, GPT4V
 
 llm = GPT4V()
 
-flow = Flow(
+agent = Agent(
     max_loops="auto",
     llm=llm,
 )
 
-flow.run(
+agent.run(
     task="Describe this image in a few sentences: ",
     img="https://unsplash.com/photos/0pIC5ByPpZY",
 )
diff --git a/playground/structs/sequential_workflow.py b/playground/structs/sequential_workflow.py
index b8e5a10b..fa7ca16a 100644
--- a/playground/structs/sequential_workflow.py
+++ b/playground/structs/sequential_workflow.py
@@ -1,5 +1,5 @@
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 
 # Example usage
@@ -8,17 +8,19 @@ llm = OpenAIChat(
     max_tokens=3000,
 )
 
-# Initialize the Flow with the language flow
-flow1 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize the Agent with the language agent
+flow1 = Agent(llm=llm, max_loops=1, dashboard=False)
 
-# Create another Flow for a different task
-flow2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Create another Agent for a different task
+flow2 = Agent(llm=llm, max_loops=1, dashboard=False)
 
 # Create the workflow
 workflow = SequentialWorkflow(max_loops=1)
 
 # Add tasks to the workflow
-workflow.add("Generate a 10,000 word blog on health and wellness.", flow1)
+workflow.add(
+    "Generate a 10,000 word blog on health and wellness.", flow1
+)
 
 # Suppose the next task takes the output of the first task as input
 workflow.add("Summarize the generated blog", flow2)
diff --git a/playground/structs/tool_utils.py b/playground/structs/tool_utils.py
new file mode 100644
index 00000000..ff7e17c2
--- /dev/null
+++ b/playground/structs/tool_utils.py
@@ -0,0 +1,19 @@
+from swarms.tools.tool import tool
+from swarms.tools.tool_func_doc_scraper import scrape_tool_func_docs
+
+
+@tool
+def search_api(query: str) -> str:
+    """Search API
+
+    Args:
+        query (str): _description_
+
+    Returns:
+        str: _description_
+    """
+    print(f"Searching API for {query}")
+
+
+tool_docs = scrape_tool_func_docs(search_api)
+print(tool_docs)
diff --git a/playground/swarms/chat.py b/playground/swarms/chat.py
index b0ebc39a..08783068 100644
--- a/playground/swarms/chat.py
+++ b/playground/swarms/chat.py
@@ -1,7 +1,11 @@
 from swarms import Orchestrator, Worker
 
 # Instantiate the Orchestrator with 10 agents
-orchestrator = Orchestrator(Worker, agent_list=[Worker] * 10, task_queue=[])
+orchestrator = Orchestrator(
+    Worker, agent_list=[Worker] * 10, task_queue=[]
+)
 
 # Agent 1 sends a message to Agent 2
-orchestrator.chat(sender_id=1, receiver_id=2, message="Hello, Agent 2!")
+orchestrator.chat(
+    sender_id=1, receiver_id=2, message="Hello, Agent 2!"
+)
diff --git a/playground/swarms/debate.py b/playground/swarms/debate.py
index 2c47ed8e..5108d527 100644
--- a/playground/swarms/debate.py
+++ b/playground/swarms/debate.py
@@ -36,7 +36,11 @@ class DialogueAgent:
         message = self.model(
             [
                 self.system_message,
-                HumanMessage(content="\n".join(self.message_history + [self.prefix])),
+                HumanMessage(
+                    content="\n".join(
+                        self.message_history + [self.prefix]
+                    )
+                ),
             ]
         )
         return message.content
@@ -74,7 +78,9 @@ class DialogueSimulator:
 
     def step(self) -> tuple[str, str]:
         # 1. choose the next speaker
-        speaker_idx = self.select_next_speaker(self._step, self.agents)
+        speaker_idx = self.select_next_speaker(
+            self._step, self.agents
+        )
         speaker = self.agents[speaker_idx]
 
         # 2. next speaker sends message
@@ -112,7 +118,9 @@ class BiddingDialogueAgent(DialogueAgent):
             message_history="\n".join(self.message_history),
             recent_message=self.message_history[-1],
         )
-        bid_string = self.model([SystemMessage(content=prompt)]).content
+        bid_string = self.model(
+            [SystemMessage(content=prompt)]
+        ).content
         return bid_string
 
 
@@ -124,19 +132,20 @@ game_description = f"""Here is the topic for the presidential debate: {topic}.
 The presidential candidates are: {', '.join(character_names)}."""
 
 player_descriptor_system_message = SystemMessage(
-    content="You can add detail to the description of each presidential candidate."
+    content=(
+        "You can add detail to the description of each presidential"
+        " candidate."
+    )
 )
 
 
 def generate_character_description(character_name):
     character_specifier_prompt = [
         player_descriptor_system_message,
-        HumanMessage(
-            content=f"""{game_description}
+        HumanMessage(content=f"""{game_description}
             Please reply with a creative description of the presidential candidate, {character_name}, in {word_limit} words or less, that emphasizes their personalities.
             Speak directly to {character_name}.
-            Do not add anything else."""
-        ),
+            Do not add anything else."""),
     ]
     character_description = ChatOpenAI(temperature=1.0)(
         character_specifier_prompt
@@ -154,10 +163,10 @@ Your goal is to be as creative as possible and make the voters think you are the
 """
 
 
-def generate_character_system_message(character_name, character_header):
-    return SystemMessage(
-        content=(
-            f"""{character_header}
+def generate_character_system_message(
+    character_name, character_header
+):
+    return SystemMessage(content=f"""{character_header}
 You will speak in the style of {character_name}, and exaggerate their personality.
 You will come up with creative ideas related to {topic}.
 Do not say the same things over and over again.
@@ -169,13 +178,12 @@ Speak only from the perspective of {character_name}.
 Stop speaking the moment you finish speaking from your perspective.
 Never forget to keep your response to {word_limit} words!
 Do not add anything else.
-    """
-        )
-    )
+    """)
 
 
 character_descriptions = [
-    generate_character_description(character_name) for character_name in character_names
+    generate_character_description(character_name)
+    for character_name in character_names
 ]
 character_headers = [
     generate_character_header(character_name, character_description)
@@ -184,8 +192,12 @@ character_headers = [
     )
 ]
 character_system_messages = [
-    generate_character_system_message(character_name, character_headers)
-    for character_name, character_headers in zip(character_names, character_headers)
+    generate_character_system_message(
+        character_name, character_headers
+    )
+    for character_name, character_headers in zip(
+        character_names, character_headers
+    )
 ]
 
 for (
@@ -207,7 +219,10 @@ for (
 
 class BidOutputParser(RegexParser):
     def get_format_instructions(self) -> str:
-        return "Your response should be an integer delimited by angled brackets, like this: <int>."
+        return (
+            "Your response should be an integer delimited by angled"
+            " brackets, like this: <int>."
+        )
 
 
 bid_parser = BidOutputParser(
@@ -248,8 +263,7 @@ for character_name, bidding_template in zip(
 
 topic_specifier_prompt = [
     SystemMessage(content="You can make a task more specific."),
-    HumanMessage(
-        content=f"""{game_description}
+    HumanMessage(content=f"""{game_description}
 
         You are the debate moderator.
         Please make the debate topic more specific.
@@ -257,10 +271,11 @@ topic_specifier_prompt = [
         Be creative and imaginative.
         Please reply with the specified topic in {word_limit} words or less.
         Speak directly to the presidential candidates: {*character_names,}.
-        Do not add anything else."""
-    ),
+        Do not add anything else."""),
 ]
-specified_topic = ChatOpenAI(temperature=1.0)(topic_specifier_prompt).content
+specified_topic = ChatOpenAI(temperature=1.0)(
+    topic_specifier_prompt
+).content
 
 print(f"Original topic:\n{topic}\n")
 print(f"Detailed topic:\n{specified_topic}\n")
@@ -271,7 +286,8 @@ print(f"Detailed topic:\n{specified_topic}\n")
     wait=tenacity.wait_none(),  # No waiting time between retries
     retry=tenacity.retry_if_exception_type(ValueError),
     before_sleep=lambda retry_state: print(
-        f"ValueError occurred: {retry_state.outcome.exception()}, retrying..."
+        f"ValueError occurred: {retry_state.outcome.exception()},"
+        " retrying..."
     ),
     retry_error_callback=lambda retry_state: 0,
 )  # Default value when all retries are exhausted
@@ -284,7 +300,9 @@ def ask_for_bid(agent) -> str:
     return bid
 
 
-def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:
+def select_next_speaker(
+    step: int, agents: List[DialogueAgent]
+) -> int:
     bids = []
     for agent in agents:
         bid = ask_for_bid(agent)
@@ -307,7 +325,9 @@ def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:
 
 characters = []
 for character_name, character_system_message, bidding_template in zip(
-    character_names, character_system_messages, character_bidding_templates
+    character_names,
+    character_system_messages,
+    character_bidding_templates,
 ):
     characters.append(
         BiddingDialogueAgent(
@@ -321,7 +341,9 @@ for character_name, character_system_message, bidding_template in zip(
 max_iters = 10
 n = 0
 
-simulator = DialogueSimulator(agents=characters, selection_function=select_next_speaker)
+simulator = DialogueSimulator(
+    agents=characters, selection_function=select_next_speaker
+)
 simulator.reset()
 simulator.inject("Debate Moderator", specified_topic)
 print(f"(Debate Moderator): {specified_topic}")
diff --git a/playground/swarms/dialogue_simulator.py b/playground/swarms/dialogue_simulator.py
index 76f31f65..ee9241b6 100644
--- a/playground/swarms/dialogue_simulator.py
+++ b/playground/swarms/dialogue_simulator.py
@@ -2,7 +2,9 @@ from swarms.swarms import DialogueSimulator
 from swarms.workers.worker import Worker
 from swarms.models import OpenAIChat
 
-llm = OpenAIChat(model_name="gpt-4", openai_api_key="api-key", temperature=0.5)
+llm = OpenAIChat(
+    model_name="gpt-4", openai_api_key="api-key", temperature=0.5
+)
 
 worker1 = Worker(
     llm=llm,
diff --git a/playground/swarms/groupchat.py b/playground/swarms/groupchat.py
index 739181d1..f53257c7 100644
--- a/playground/swarms/groupchat.py
+++ b/playground/swarms/groupchat.py
@@ -1,4 +1,4 @@
-from swarms import OpenAI, Flow
+from swarms import OpenAI, Agent
 from swarms.swarms.groupchat import GroupChatManager, GroupChat
 
 
@@ -10,29 +10,29 @@ llm = OpenAI(
     max_tokens=3000,
 )
 
-# Initialize the flow
-flow1 = Flow(
+# Initialize the agent
+flow1 = Agent(
     llm=llm,
     max_loops=1,
     system_message="YOU ARE SILLY, YOU OFFER NOTHING OF VALUE",
     name="silly",
     dashboard=True,
 )
-flow2 = Flow(
+flow2 = Agent(
     llm=llm,
     max_loops=1,
     system_message="YOU ARE VERY SMART AND ANSWER RIDDLES",
     name="detective",
     dashboard=True,
 )
-flow3 = Flow(
+flow3 = Agent(
     llm=llm,
     max_loops=1,
     system_message="YOU MAKE RIDDLES",
     name="riddler",
     dashboard=True,
 )
-manager = Flow(
+manager = Agent(
     llm=llm,
     max_loops=1,
     system_message="YOU ARE A GROUP CHAT MANAGER",
@@ -45,5 +45,7 @@ manager = Flow(
 agents = [flow1, flow2, flow3]
 
 group_chat = GroupChat(agents=agents, messages=[], max_round=10)
-chat_manager = GroupChatManager(groupchat=group_chat, selector=manager)
+chat_manager = GroupChatManager(
+    groupchat=group_chat, selector=manager
+)
 chat_history = chat_manager("Write me a riddle")
diff --git a/playground/swarms/multi_agent_debate.py b/playground/swarms/multi_agent_debate.py
index f0bec797..6124a21c 100644
--- a/playground/swarms/multi_agent_debate.py
+++ b/playground/swarms/multi_agent_debate.py
@@ -1,4 +1,7 @@
-from swarms.swarms.multi_agent_debate import MultiAgentDebate, select_speaker
+from swarms.swarms.multi_agent_debate import (
+    MultiAgentDebate,
+    select_speaker,
+)
 from swarms.workers.worker import Worker
 from swarms.models import OpenAIChat
 
@@ -36,7 +39,11 @@ agents = [worker1, worker2, worker3]
 debate = MultiAgentDebate(agents, select_speaker)
 
 # Run task
-task = "What were the winning boston marathon times for the past 5 years (ending in 2022)? Generate a table of the year, name, country of origin, and times."
+task = (
+    "What were the winning boston marathon times for the past 5 years"
+    " (ending in 2022)? Generate a table of the year, name, country"
+    " of origin, and times."
+)
 results = debate.run(task, max_iters=4)
 
 # Print results
diff --git a/playground/swarms/orchestrate.py b/playground/swarms/orchestrate.py
index e43b75e3..b0e17588 100644
--- a/playground/swarms/orchestrate.py
+++ b/playground/swarms/orchestrate.py
@@ -7,7 +7,13 @@ node = Worker(
 
 
 # Instantiate the Orchestrator with 10 agents
-orchestrator = Orchestrator(node, agent_list=[node] * 10, task_queue=[])
+orchestrator = Orchestrator(
+    node, agent_list=[node] * 10, task_queue=[]
+)
 
 # Agent 7 sends a message to Agent 9
-orchestrator.chat(sender_id=7, receiver_id=9, message="Can you help me with this task?")
+orchestrator.chat(
+    sender_id=7,
+    receiver_id=9,
+    message="Can you help me with this task?",
+)
diff --git a/playground/swarms/orchestrator.py b/playground/swarms/orchestrator.py
index e43b75e3..b0e17588 100644
--- a/playground/swarms/orchestrator.py
+++ b/playground/swarms/orchestrator.py
@@ -7,7 +7,13 @@ node = Worker(
 
 
 # Instantiate the Orchestrator with 10 agents
-orchestrator = Orchestrator(node, agent_list=[node] * 10, task_queue=[])
+orchestrator = Orchestrator(
+    node, agent_list=[node] * 10, task_queue=[]
+)
 
 # Agent 7 sends a message to Agent 9
-orchestrator.chat(sender_id=7, receiver_id=9, message="Can you help me with this task?")
+orchestrator.chat(
+    sender_id=7,
+    receiver_id=9,
+    message="Can you help me with this task?",
+)
diff --git a/playground/swarms/swarms_example.py b/playground/swarms/swarms_example.py
index 6dabe4a1..9f015807 100644
--- a/playground/swarms/swarms_example.py
+++ b/playground/swarms/swarms_example.py
@@ -7,7 +7,10 @@ api_key = ""
 swarm = HierarchicalSwarm(api_key)
 
 # Define an objective
-objective = "Find 20 potential customers for a HierarchicalSwarm based AI Agent automation infrastructure"
+objective = (
+    "Find 20 potential customers for a HierarchicalSwarm based AI"
+    " Agent automation infrastructure"
+)
 
 # Run HierarchicalSwarm
 swarm.run(objective)
diff --git a/playground/swarms_example.ipynb b/playground/swarms_example.ipynb
index 49ea5104..2d7779b1 100644
--- a/playground/swarms_example.ipynb
+++ b/playground/swarms_example.ipynb
@@ -42,7 +42,7 @@
       "cell_type": "code",
       "source": [
         "from swarms.models import OpenAIChat\n",
-        "from swarms.structs import Flow\n",
+        "from swarms.structs import Agent\n",
         "\n",
         "api_key = \"\"\n",
         "\n",
@@ -56,7 +56,7 @@
         "\n",
         "\n",
         "## Initialize the workflow\n",
-        "flow = Flow(\n",
+        "agent = Agent(\n",
         "    llm=llm,\n",
         "    max_loops=5,\n",
         "    dashboard=True,\n",
@@ -69,16 +69,16 @@
         "    # dynamic_temperature=False,  # Set to 'True' for dynamic temperature handling.\n",
         ")\n",
         "\n",
-        "# out = flow.load_state(\"flow_state.json\")\n",
-        "# temp = flow.dynamic_temperature()\n",
-        "# filter = flow.add_response_filter(\"Trump\")\n",
-        "out = flow.run(\n",
+        "# out = agent.load_state(\"flow_state.json\")\n",
+        "# temp = agent.dynamic_temperature()\n",
+        "# filter = agent.add_response_filter(\"Trump\")\n",
+        "out = agent.run(\n",
         "    \"Generate a 10,000 word blog on mental clarity and the benefits of meditation.\"\n",
         ")\n",
-        "# out = flow.validate_response(out)\n",
-        "# out = flow.analyze_feedback(out)\n",
-        "# out = flow.print_history_and_memory()\n",
-        "# # out = flow.save_state(\"flow_state.json\")\n",
+        "# out = agent.validate_response(out)\n",
+        "# out = agent.analyze_feedback(out)\n",
+        "# out = agent.print_history_and_memory()\n",
+        "# # out = agent.save_state(\"flow_state.json\")\n",
         "# print(out)"
       ],
       "metadata": {
diff --git a/playground/tools/agent_with_tools.py b/playground/tools/agent_with_tools.py
new file mode 100644
index 00000000..ee4a8ef7
--- /dev/null
+++ b/playground/tools/agent_with_tools.py
@@ -0,0 +1,39 @@
+import os
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
+from swarms.tools.tool import tool
+from dotenv import load_dotenv
+
+load_dotenv()
+
+api_key = os.environ.get("OPENAI_API_KEY")
+
+
+llm = OpenAIChat(api_key=api_key)
+
+# @tool
+# def search_api(query: str) -> str:
+#     """Search API
+
+#     Args:
+#         query (str): _description_
+
+#     Returns:
+#         str: _description_
+#     """
+#     print(f"Searching API for {query}")
+
+
+## Initialize the workflow
+agent = Agent(
+    llm=llm,
+    max_loops=5,
+    # tools=[search_api],
+    dashboard=True,
+)
+
+out = agent.run(
+    "Use the search api to find the best restaurants in New York"
+    " City."
+)
+print(out)
diff --git a/playground/tools/tool_prompt_scaper.py b/playground/tools/tool_prompt_scaper.py
new file mode 100644
index 00000000..2c0434d6
--- /dev/null
+++ b/playground/tools/tool_prompt_scaper.py
@@ -0,0 +1,22 @@
+from swarms.tools.tool import tool
+from swarms.tools.tool_func_doc_scraper import scrape_tool_func_docs
+
+# Define a tool by decorating a function with the tool decorator and providing a docstring
+
+
+@tool(return_direct=True)
+def search_api(query: str):
+    """Search the web for the query
+
+    Args:
+        query (str): _description_
+
+    Returns:
+        _type_: _description_
+    """
+    return f"Search results for {query}"
+
+
+# Scrape the tool func docs to prepare for injection into the agent prompt
+out = scrape_tool_func_docs(search_api)
+print(out)
diff --git a/pyproject.toml b/pyproject.toml
index 075bbd15..c182abd9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
 name = "swarms"
-version = "2.3.9"
+version = "2.6.0"
 description = "Swarms - Pytorch"
 license = "MIT"
 authors = ["Kye Gomez <kye@apac.ai>"]
@@ -18,22 +18,23 @@ classifiers = [
     "Intended Audience :: Developers",
     "Topic :: Scientific/Engineering :: Artificial Intelligence",
     "License :: OSI Approved :: MIT License",
-    "Programming Language :: Python :: 3.6"
+    "Programming Language :: Python :: 3.10"
 ]
 
 [tool.poetry.dependencies]
-python = "^3.8.1"
-transformers = "*"
+python = "^3.9.1"
+torch = "2.1.1"
+transformers = "2.10"
 openai = "0.28.0"
 langchain = "*"
 asyncio = "*"
 nest_asyncio = "*"
 einops = "*"
 google-generativeai = "*"
-torch = "*"
 langchain-experimental = "*"
 playwright = "*"
 duckduckgo-search = "*"
+opencv-python-headless = "*"
 faiss-cpu = "*"
 backoff = "*"
 marshmallow = "*"
@@ -52,7 +53,7 @@ ratelimit = "*"
 beautifulsoup4 = "*"
 cohere = "*"
 huggingface-hub = "*"
-pydantic = "*"
+pydantic = "1.10.12"
 tenacity = "*"
 Pillow = "*"
 chromadb = "*"
@@ -67,7 +68,7 @@ torchvision = "*"
 rich = "*"
 
 [tool.poetry.group.lint.dependencies]
-ruff = "^0.0.249"
+ruff = ">=0.0.249,<0.1.7"
 types-toml = "^0.10.8.1"
 types-redis = "^4.3.21.6"
 types-pytz = "^2023.3.0.0"
@@ -77,11 +78,18 @@ mypy-protobuf = "^3.0.0"
 
 
 [tool.autopep8]
-max_line_length = 120
+max_line_length = 70
 ignore = "E501,W6"  # or ["E501", "W6"]
 in-place = true
 recursive = true
 aggressive = 3
 
 [tool.ruff]
-line-length = 120
\ No newline at end of file
+line-length = 70
+
+[tool.black]
+line-length = 70
+target-version = ['py38']
+preview = true
+
+
diff --git a/requirements.txt b/requirements.txt
index 2330d399..0bc6a065 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,34 +1,28 @@
-# faiss-gpu
-transformers
-revChatGPT
+torch==2.1.1
+transformers>2.10
 pandas
 langchain
 nest_asyncio
-pegasusx
-google-generativeai 
-EdgeGPT
 langchain-experimental
 playwright
 wget==3.2
 simpleaichat
 httpx
-torch
 open_clip_torch
 ggl
 beautifulsoup4
 google-search-results==2.4.2
 Pillow
 faiss-cpu
-openai
+openai==0.28.0
 attrs
 datasets
+pydantic==1.10.12
 soundfile
 huggingface-hub
 google-generativeai
 sentencepiece
-duckduckgo-search
 PyPDF2
-agent-protocol
 accelerate
 chromadb
 tiktoken
@@ -56,16 +50,13 @@ openai
 opencv-python
 prettytable
 safetensors
-streamlit
 test-tube
 timm
 torchmetrics
-transformers
 webdataset
 marshmallow
 yapf
 autopep8
-dalle3
 cohere
 torchvision
 rich
@@ -74,5 +65,4 @@ rich
 mkdocs
 mkdocs-material
 mkdocs-glightbox
-
 pre-commit
diff --git a/code_quality.sh b/scripts/code_quality.sh
similarity index 97%
rename from code_quality.sh
rename to scripts/code_quality.sh
index 1c8c95b5..90153258 100755
--- a/code_quality.sh
+++ b/scripts/code_quality.sh
@@ -13,7 +13,7 @@ black --experimental-string-processing swarms/
 
 # Run ruff on the 'swarms' directory.
 # Add any additional flags if needed according to your version of ruff.
-#ruff --unsafe_fix
+ruff --unsafe_fix
 
 # YAPF
 yapf --recursive --in-place --verbose --style=google --parallel swarms
diff --git a/scripts/test_name.sh b/scripts/test_name.sh
new file mode 100755
index 00000000..cdc6a013
--- /dev/null
+++ b/scripts/test_name.sh
@@ -0,0 +1,8 @@
+find ./tests -name "*.py" -type f | while read file
+do
+  filename=$(basename "$file")
+  dir=$(dirname "$file")
+  if [[ $filename != test_* ]]; then
+    mv "$file" "$dir/test_$filename"
+  fi
+done
\ No newline at end of file
diff --git a/scripts/tests.sh b/scripts/tests.sh
new file mode 100644
index 00000000..13f4111a
--- /dev/null
+++ b/scripts/tests.sh
@@ -0,0 +1 @@
+find ./tests -name '*.py' -exec pytest {} \;
\ No newline at end of file
diff --git a/sequential_workflow_example.py b/sequential_workflow_example.py
index 76c17ab2..38cf5559 100644
--- a/sequential_workflow_example.py
+++ b/sequential_workflow_example.py
@@ -1,44 +1,48 @@
-from swarms.models import OpenAIChat, BioGPT, Anthropic
-from swarms.structs import Flow
+import os
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
+from dotenv import load_dotenv
 
+load_dotenv()
 
-# Example usage
-api_key = ""  # Your actual API key here
+# Load the environment variables
+api_key = os.getenv("OPENAI_API_KEY")
 
-# Initialize the language flow
+
+# Initialize the language agent
+# Initialize the language model
 llm = OpenAIChat(
-    openai_api_key=api_key,
     temperature=0.5,
-    max_tokens=3000,
+    model_name="gpt-4",
+    openai_api_key=api_key,
+    max_tokens=4000
 )
 
-biochat = BioGPT()
 
-# Use Anthropic
-anthropic = Anthropic()
-
-# Initialize the agent with the language flow
-agent1 = Flow(llm=llm, max_loops=1, dashboard=False)
-
-# Create another agent for a different task
-agent2 = Flow(llm=llm, max_loops=1, dashboard=False)
+# Initialize the agent with the language agent
+agent1 = Agent(
+    llm=llm,
+    max_loops=1,
+)
 
 # Create another agent for a different task
-agent3 = Flow(llm=biochat, max_loops=1, dashboard=False)
-
-# agent4 = Flow(llm=anthropic, max_loops="auto")
+agent2 = Agent(llm=llm, max_loops=1)
 
 # Create the workflow
 workflow = SequentialWorkflow(max_loops=1)
 
 # Add tasks to the workflow
-workflow.add("Generate a 10,000 word blog on health and wellness.", agent1)
+workflow.add(
+    agent1,
+    "Generate a 10,000 word blog on health and wellness.",
+)
 
 # Suppose the next task takes the output of the first task as input
-workflow.add("Summarize the generated blog", agent2)
-
-workflow.add("Create a references sheet of materials for the curriculm", agent3)
+workflow.add(
+    agent2,
+    "Summarize the generated blog",
+)
 
 # Run the workflow
 workflow.run()
diff --git a/swarms/__init__.py b/swarms/__init__.py
index d876c04e..9ceb78f2 100644
--- a/swarms/__init__.py
+++ b/swarms/__init__.py
@@ -1,18 +1,6 @@
-import logging
-import os
-import warnings
+from swarms.utils.disable_logging import disable_logging
 
-warnings.filterwarnings("ignore", category=UserWarning)
-
-# disable tensorflow warnings
-os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
-
-try:
-    log = logging.getLogger("pytorch")
-    log.propagate = False
-    log.setLevel(logging.ERROR)
-except Exception as error:
-    print(f"Pytorch logging not disabled: {error}")
+disable_logging()
 
 from swarms.agents import *  # noqa: E402, F403
 from swarms.swarms import *  # noqa: E402, F403
diff --git a/swarms/agents/__init__.py b/swarms/agents/__init__.py
index 455b95ee..4f6e12d6 100644
--- a/swarms/agents/__init__.py
+++ b/swarms/agents/__init__.py
@@ -3,7 +3,6 @@ from swarms.agents.message import Message
 
 # from swarms.agents.stream_response import stream
 from swarms.agents.base import AbstractAgent
-from swarms.agents.registry import Registry
 
 # from swarms.agents.idea_to_image_agent import Idea2Image
 
@@ -13,5 +12,4 @@ __all__ = [
     # "OmniModalAgent",
     "Message",
     "AbstractAgent",
-    "Registry",
 ]
diff --git a/swarms/agents/omni_modal_agent.py b/swarms/agents/omni_modal_agent.py
index 007a2219..6a22c477 100644
--- a/swarms/agents/omni_modal_agent.py
+++ b/swarms/agents/omni_modal_agent.py
@@ -18,7 +18,12 @@ from swarms.agents.message import Message
 
 class Step:
     def __init__(
-        self, task: str, id: int, dep: List[int], args: Dict[str, str], tool: BaseTool
+        self,
+        task: str,
+        id: int,
+        dep: List[int],
+        args: Dict[str, str],
+        tool: BaseTool,
     ):
         self.task = task
         self.id = id
diff --git a/swarms/agents/registry.py b/swarms/agents/registry.py
deleted file mode 100644
index aa1f1375..00000000
--- a/swarms/agents/registry.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import Dict
-
-from pydantic import BaseModel
-
-
-class Registry(BaseModel):
-    """Registry for storing and building classes."""
-
-    name: str
-    entries: Dict = {}
-
-    def register(self, key: str):
-        def decorator(class_builder):
-            self.entries[key] = class_builder
-            return class_builder
-
-        return decorator
-
-    def build(self, type: str, **kwargs):
-        if type not in self.entries:
-            raise ValueError(
-                f"{type} is not registered. Please register with the"
-                f' .register("{type}") method provided in {self.name} registry'
-            )
-        return self.entries[type](**kwargs)
-
-    def get_all_entries(self):
-        return self.entries
diff --git a/swarms/memory/__init__.py b/swarms/memory/__init__.py
index 41be1c6f..e916d5a8 100644
--- a/swarms/memory/__init__.py
+++ b/swarms/memory/__init__.py
@@ -1,11 +1,3 @@
-from swarms.memory.pinecone import PineconeVector
-from swarms.memory.base import BaseVectorStore
-from swarms.memory.pg import PgVectorVectorStore
-from swarms.memory.ocean import OceanDB
-
-__all__ = [
-    "BaseVectorStore",
-    "PineconeVector",
-    "PgVectorVectorStore",
-    "OceanDB",
-]
+# from swarms.memory.pinecone import PineconeVector
+# from swarms.memory.base import BaseVectorStore
+# from swarms.memory.pg import PgVectorVectorStore
diff --git a/swarms/memory/agent_memory.py b/swarms/memory/agent_memory.py
deleted file mode 100644
index f246c6cf..00000000
--- a/swarms/memory/agent_memory.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from typing import Any, Dict, List
-
-from swarms.memory.base_memory import BaseChatMemory, get_prompt_input_key
-from swarms.memory.base import VectorStoreRetriever
-
-
-class AgentMemory(BaseChatMemory):
-    retriever: VectorStoreRetriever
-    """VectorStoreRetriever object to connect to."""
-
-    @property
-    def memory_variables(self) -> List[str]:
-        return ["chat_history", "relevant_context"]
-
-    def _get_prompt_input_key(self, inputs: Dict[str, Any]) -> str:
-        """Get the input key for the prompt."""
-        if self.input_key is None:
-            return get_prompt_input_key(inputs, self.memory_variables)
-        return self.input_key
-
-    def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
-        input_key = self._get_prompt_input_key(inputs)
-        query = inputs[input_key]
-        docs = self.retriever.get_relevant_documents(query)
-        return {
-            "chat_history": self.chat_memory.messages[-10:],
-            "relevant_context": docs,
-        }
diff --git a/swarms/memory/base.py b/swarms/memory/base.py
index 7f71c4b9..2e9574b8 100644
--- a/swarms/memory/base.py
+++ b/swarms/memory/base.py
@@ -3,14 +3,12 @@ from concurrent import futures
 from dataclasses import dataclass
 from typing import Optional, Any
 from attr import define, field, Factory
-from swarms.utils.futures import execute_futures_dict
+from swarms.utils.execute_futures import execute_futures_dict
 from griptape.artifacts import TextArtifact
 
 
 @define
 class BaseVectorStore(ABC):
-    """ """
-
     DEFAULT_QUERY_COUNT = 5
 
     @dataclass
@@ -30,19 +28,24 @@ class BaseVectorStore(ABC):
 
     embedding_driver: Any
     futures_executor: futures.Executor = field(
-        default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True
+        default=Factory(lambda: futures.ThreadPoolExecutor()),
+        kw_only=True,
     )
 
     def upsert_text_artifacts(
         self,
         artifacts: dict[str, list[TextArtifact]],
         meta: Optional[dict] = None,
-        **kwargs
+        **kwargs,
     ) -> None:
         execute_futures_dict(
             {
                 namespace: self.futures_executor.submit(
-                    self.upsert_text_artifact, a, namespace, meta, **kwargs
+                    self.upsert_text_artifact,
+                    a,
+                    namespace,
+                    meta,
+                    **kwargs,
                 )
                 for namespace, artifact_list in artifacts.items()
                 for a in artifact_list
@@ -54,7 +57,7 @@ class BaseVectorStore(ABC):
         artifact: TextArtifact,
         namespace: Optional[str] = None,
         meta: Optional[dict] = None,
-        **kwargs
+        **kwargs,
     ) -> str:
         if not meta:
             meta = {}
@@ -64,10 +67,16 @@ class BaseVectorStore(ABC):
         if artifact.embedding:
             vector = artifact.embedding
         else:
-            vector = artifact.generate_embedding(self.embedding_driver)
+            vector = artifact.generate_embedding(
+                self.embedding_driver
+            )
 
         return self.upsert_vector(
-            vector, vector_id=artifact.id, namespace=namespace, meta=meta, **kwargs
+            vector,
+            vector_id=artifact.id,
+            namespace=namespace,
+            meta=meta,
+            **kwargs,
         )
 
     def upsert_text(
@@ -76,14 +85,14 @@ class BaseVectorStore(ABC):
         vector_id: Optional[str] = None,
         namespace: Optional[str] = None,
         meta: Optional[dict] = None,
-        **kwargs
+        **kwargs,
     ) -> str:
         return self.upsert_vector(
             self.embedding_driver.embed_string(string),
             vector_id=vector_id,
             namespace=namespace,
             meta=meta if meta else {},
-            **kwargs
+            **kwargs,
         )
 
     @abstractmethod
@@ -93,16 +102,20 @@ class BaseVectorStore(ABC):
         vector_id: Optional[str] = None,
         namespace: Optional[str] = None,
         meta: Optional[dict] = None,
-        **kwargs
+        **kwargs,
     ) -> str:
         ...
 
     @abstractmethod
-    def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Entry:
+    def load_entry(
+        self, vector_id: str, namespace: Optional[str] = None
+    ) -> Entry:
         ...
 
     @abstractmethod
-    def load_entries(self, namespace: Optional[str] = None) -> list[Entry]:
+    def load_entries(
+        self, namespace: Optional[str] = None
+    ) -> list[Entry]:
         ...
 
     @abstractmethod
@@ -112,6 +125,6 @@ class BaseVectorStore(ABC):
         count: Optional[int] = None,
         namespace: Optional[str] = None,
         include_vectors: bool = False,
-        **kwargs
+        **kwargs,
     ) -> list[QueryResult]:
         ...
diff --git a/swarms/memory/base_vector_db.py b/swarms/memory/base_vector_db.py
new file mode 100644
index 00000000..fc58bf36
--- /dev/null
+++ b/swarms/memory/base_vector_db.py
@@ -0,0 +1,60 @@
+from abc import ABC, abstractmethod
+from typing import Any, Dict
+
+
+class VectorDatabase(ABC):
+    @abstractmethod
+    def add(
+        self, vector: Dict[str, Any], metadata: Dict[str, Any]
+    ) -> None:
+        """
+        add a vector into the database.
+
+        Args:
+            vector (Dict[str, Any]): The vector to add.
+            metadata (Dict[str, Any]): Metadata associated with the vector.
+        """
+        pass
+
+    @abstractmethod
+    def query(
+        self, vector: Dict[str, Any], num_results: int
+    ) -> Dict[str, Any]:
+        """
+        Query the database for vectors similar to the given vector.
+
+        Args:
+            vector (Dict[str, Any]): The vector to compare against.
+            num_results (int): The number of similar vectors to return.
+
+        Returns:
+            Dict[str, Any]: The most similar vectors and their associated metadata.
+        """
+        pass
+
+    @abstractmethod
+    def delete(self, vector_id: str) -> None:
+        """
+        Delete a vector from the database.
+
+        Args:
+            vector_id (str): The ID of the vector to delete.
+        """
+        pass
+
+    @abstractmethod
+    def update(
+        self,
+        vector_id: str,
+        vector: Dict[str, Any],
+        metadata: Dict[str, Any],
+    ) -> None:
+        """
+        Update a vector in the database.
+
+        Args:
+            vector_id (str): The ID of the vector to update.
+            vector (Dict[str, Any]): The new vector.
+            metadata (Dict[str, Any]): The new metadata.
+        """
+        pass
diff --git a/swarms/memory/chroma.py b/swarms/memory/chroma.py
index e69de29b..79b92964 100644
--- a/swarms/memory/chroma.py
+++ b/swarms/memory/chroma.py
@@ -0,0 +1,753 @@
+from __future__ import annotations
+
+import logging
+import uuid
+from typing import (
+    TYPE_CHECKING,
+    Any,
+    Callable,
+    Dict,
+    Iterable,
+    List,
+    Optional,
+    Tuple,
+    Type,
+)
+
+import numpy as np
+
+from swarms.structs.document import Document
+from swarms.models.embeddings_base import Embeddings
+from langchain.schema.vectorstore import VectorStore
+from langchain.utils import xor_args
+from langchain.vectorstores.utils import maximal_marginal_relevance
+
+if TYPE_CHECKING:
+    import chromadb
+    import chromadb.config
+    from chromadb.api.types import ID, OneOrMany, Where, WhereDocument
+
+logger = logging.getLogger()
+DEFAULT_K = 4  # Number of Documents to return.
+
+
+def _results_to_docs(results: Any) -> List[Document]:
+    return [doc for doc, _ in _results_to_docs_and_scores(results)]
+
+
+def _results_to_docs_and_scores(
+    results: Any,
+) -> List[Tuple[Document, float]]:
+    return [
+        # TODO: Chroma can do batch querying,
+        # we shouldn't hard code to the 1st result
+        (
+            Document(
+                page_content=result[0], metadata=result[1] or {}
+            ),
+            result[2],
+        )
+        for result in zip(
+            results["documents"][0],
+            results["metadatas"][0],
+            results["distances"][0],
+        )
+    ]
+
+
+class Chroma(VectorStore):
+    """`ChromaDB` vector store.
+
+    To use, you should have the ``chromadb`` python package installed.
+
+    Example:
+        .. code-block:: python
+
+                from langchain.vectorstores import Chroma
+                from langchain.embeddings.openai import OpenAIEmbeddings
+
+                embeddings = OpenAIEmbeddings()
+                vectorstore = Chroma("langchain_store", embeddings)
+    """
+
+    _LANGCHAIN_DEFAULT_COLLECTION_NAME = "langchain"
+
+    def __init__(
+        self,
+        collection_name: str = _LANGCHAIN_DEFAULT_COLLECTION_NAME,
+        embedding_function: Optional[Embeddings] = None,
+        persist_directory: Optional[str] = None,
+        client_settings: Optional[chromadb.config.Settings] = None,
+        collection_metadata: Optional[Dict] = None,
+        client: Optional[chromadb.Client] = None,
+        relevance_score_fn: Optional[Callable[[float], float]] = None,
+    ) -> None:
+        """Initialize with a Chroma client."""
+        try:
+            import chromadb
+            import chromadb.config
+        except ImportError:
+            raise ImportError(
+                "Could not import chromadb python package. "
+                "Please install it with `pip install chromadb`."
+            )
+
+        if client is not None:
+            self._client_settings = client_settings
+            self._client = client
+            self._persist_directory = persist_directory
+        else:
+            if client_settings:
+                # If client_settings is provided with persist_directory specified,
+                # then it is "in-memory and persisting to disk" mode.
+                client_settings.persist_directory = (
+                    persist_directory
+                    or client_settings.persist_directory
+                )
+                if client_settings.persist_directory is not None:
+                    # Maintain backwards compatibility with chromadb < 0.4.0
+                    major, minor, _ = chromadb.__version__.split(".")
+                    if int(major) == 0 and int(minor) < 4:
+                        client_settings.chroma_db_impl = (
+                            "duckdb+parquet"
+                        )
+
+                _client_settings = client_settings
+            elif persist_directory:
+                # Maintain backwards compatibility with chromadb < 0.4.0
+                major, minor, _ = chromadb.__version__.split(".")
+                if int(major) == 0 and int(minor) < 4:
+                    _client_settings = chromadb.config.Settings(
+                        chroma_db_impl="duckdb+parquet",
+                    )
+                else:
+                    _client_settings = chromadb.config.Settings(
+                        is_persistent=True
+                    )
+                _client_settings.persist_directory = persist_directory
+            else:
+                _client_settings = chromadb.config.Settings()
+            self._client_settings = _client_settings
+            self._client = chromadb.Client(_client_settings)
+            self._persist_directory = (
+                _client_settings.persist_directory
+                or persist_directory
+            )
+
+        self._embedding_function = embedding_function
+        self._collection = self._client.get_or_create_collection(
+            name=collection_name,
+            embedding_function=(
+                self._embedding_function.embed_documents
+                if self._embedding_function is not None
+                else None
+            ),
+            metadata=collection_metadata,
+        )
+        self.override_relevance_score_fn = relevance_score_fn
+
+    @property
+    def embeddings(self) -> Optional[Embeddings]:
+        return self._embedding_function
+
+    @xor_args(("query_texts", "query_embeddings"))
+    def __query_collection(
+        self,
+        query_texts: Optional[List[str]] = None,
+        query_embeddings: Optional[List[List[float]]] = None,
+        n_results: int = 4,
+        where: Optional[Dict[str, str]] = None,
+        where_document: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Document]:
+        """Query the chroma collection."""
+        try:
+            import chromadb  # noqa: F401
+        except ImportError:
+            raise ValueError(
+                "Could not import chromadb python package. "
+                "Please install it with `pip install chromadb`."
+            )
+        return self._collection.query(
+            query_texts=query_texts,
+            query_embeddings=query_embeddings,
+            n_results=n_results,
+            where=where,
+            where_document=where_document,
+            **kwargs,
+        )
+
+    def add_texts(
+        self,
+        texts: Iterable[str],
+        metadatas: Optional[List[dict]] = None,
+        ids: Optional[List[str]] = None,
+        **kwargs: Any,
+    ) -> List[str]:
+        """Run more texts through the embeddings and add to the vectorstore.
+
+        Args:
+            texts (Iterable[str]): Texts to add to the vectorstore.
+            metadatas (Optional[List[dict]], optional): Optional list of metadatas.
+            ids (Optional[List[str]], optional): Optional list of IDs.
+
+        Returns:
+            List[str]: List of IDs of the added texts.
+        """
+        # TODO: Handle the case where the user doesn't provide ids on the Collection
+        if ids is None:
+            ids = [str(uuid.uuid1()) for _ in texts]
+        embeddings = None
+        texts = list(texts)
+        if self._embedding_function is not None:
+            embeddings = self._embedding_function.embed_documents(
+                texts
+            )
+        if metadatas:
+            # fill metadatas with empty dicts if somebody
+            # did not specify metadata for all texts
+            length_diff = len(texts) - len(metadatas)
+            if length_diff:
+                metadatas = metadatas + [{}] * length_diff
+            empty_ids = []
+            non_empty_ids = []
+            for idx, m in enumerate(metadatas):
+                if m:
+                    non_empty_ids.append(idx)
+                else:
+                    empty_ids.append(idx)
+            if non_empty_ids:
+                metadatas = [metadatas[idx] for idx in non_empty_ids]
+                texts_with_metadatas = [
+                    texts[idx] for idx in non_empty_ids
+                ]
+                embeddings_with_metadatas = (
+                    [embeddings[idx] for idx in non_empty_ids]
+                    if embeddings
+                    else None
+                )
+                ids_with_metadata = [
+                    ids[idx] for idx in non_empty_ids
+                ]
+                try:
+                    self._collection.upsert(
+                        metadatas=metadatas,
+                        embeddings=embeddings_with_metadatas,
+                        documents=texts_with_metadatas,
+                        ids=ids_with_metadata,
+                    )
+                except ValueError as e:
+                    if "Expected metadata value to be" in str(e):
+                        msg = (
+                            "Try filtering complex metadata from the"
+                            " document"
+                            " using "
+                            "langchain.vectorstores.utils.filter_complex_metadata."
+                        )
+                        raise ValueError(e.args[0] + "\n\n" + msg)
+                    else:
+                        raise e
+            if empty_ids:
+                texts_without_metadatas = [
+                    texts[j] for j in empty_ids
+                ]
+                embeddings_without_metadatas = (
+                    [embeddings[j] for j in empty_ids]
+                    if embeddings
+                    else None
+                )
+                ids_without_metadatas = [ids[j] for j in empty_ids]
+                self._collection.upsert(
+                    embeddings=embeddings_without_metadatas,
+                    documents=texts_without_metadatas,
+                    ids=ids_without_metadatas,
+                )
+        else:
+            self._collection.upsert(
+                embeddings=embeddings,
+                documents=texts,
+                ids=ids,
+            )
+        return ids
+
+    def similarity_search(
+        self,
+        query: str,
+        k: int = DEFAULT_K,
+        filter: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Document]:
+        """Run similarity search with Chroma.
+
+        Args:
+            query (str): Query text to search for.
+            k (int): Number of results to return. Defaults to 4.
+            filter (Optional[Dict[str, str]]): Filter by metadata. Defaults to None.
+
+        Returns:
+            List[Document]: List of documents most similar to the query text.
+        """
+        docs_and_scores = self.similarity_search_with_score(
+            query, k, filter=filter
+        )
+        return [doc for doc, _ in docs_and_scores]
+
+    def similarity_search_by_vector(
+        self,
+        embedding: List[float],
+        k: int = DEFAULT_K,
+        filter: Optional[Dict[str, str]] = None,
+        where_document: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Document]:
+        """Return docs most similar to embedding vector.
+        Args:
+            embedding (List[float]): Embedding to look up documents similar to.
+            k (int): Number of Documents to return. Defaults to 4.
+            filter (Optional[Dict[str, str]]): Filter by metadata. Defaults to None.
+        Returns:
+            List of Documents most similar to the query vector.
+        """
+        results = self.__query_collection(
+            query_embeddings=embedding,
+            n_results=k,
+            where=filter,
+            where_document=where_document,
+        )
+        return _results_to_docs(results)
+
+    def similarity_search_by_vector_with_relevance_scores(
+        self,
+        embedding: List[float],
+        k: int = DEFAULT_K,
+        filter: Optional[Dict[str, str]] = None,
+        where_document: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Tuple[Document, float]]:
+        """
+        Return docs most similar to embedding vector and similarity score.
+
+        Args:
+            embedding (List[float]): Embedding to look up documents similar to.
+            k (int): Number of Documents to return. Defaults to 4.
+            filter (Optional[Dict[str, str]]): Filter by metadata. Defaults to None.
+
+        Returns:
+            List[Tuple[Document, float]]: List of documents most similar to
+            the query text and cosine distance in float for each.
+            Lower score represents more similarity.
+        """
+        results = self.__query_collection(
+            query_embeddings=embedding,
+            n_results=k,
+            where=filter,
+            where_document=where_document,
+        )
+        return _results_to_docs_and_scores(results)
+
+    def similarity_search_with_score(
+        self,
+        query: str,
+        k: int = DEFAULT_K,
+        filter: Optional[Dict[str, str]] = None,
+        where_document: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Tuple[Document, float]]:
+        """Run similarity search with Chroma with distance.
+
+        Args:
+            query (str): Query text to search for.
+            k (int): Number of results to return. Defaults to 4.
+            filter (Optional[Dict[str, str]]): Filter by metadata. Defaults to None.
+
+        Returns:
+            List[Tuple[Document, float]]: List of documents most similar to
+            the query text and cosine distance in float for each.
+            Lower score represents more similarity.
+        """
+        if self._embedding_function is None:
+            results = self.__query_collection(
+                query_texts=[query],
+                n_results=k,
+                where=filter,
+                where_document=where_document,
+            )
+        else:
+            query_embedding = self._embedding_function.embed_query(
+                query
+            )
+            results = self.__query_collection(
+                query_embeddings=[query_embedding],
+                n_results=k,
+                where=filter,
+                where_document=where_document,
+            )
+
+        return _results_to_docs_and_scores(results)
+
+    def _select_relevance_score_fn(self) -> Callable[[float], float]:
+        """
+        The 'correct' relevance function
+        may differ depending on a few things, including:
+        - the distance / similarity metric used by the VectorStore
+        - the scale of your embeddings (OpenAI's are unit normed. Many others are not!)
+        - embedding dimensionality
+        - etc.
+        """
+        if self.override_relevance_score_fn:
+            return self.override_relevance_score_fn
+
+        distance = "l2"
+        distance_key = "hnsw:space"
+        metadata = self._collection.metadata
+
+        if metadata and distance_key in metadata:
+            distance = metadata[distance_key]
+
+        if distance == "cosine":
+            return self._cosine_relevance_score_fn
+        elif distance == "l2":
+            return self._euclidean_relevance_score_fn
+        elif distance == "ip":
+            return self._max_inner_product_relevance_score_fn
+        else:
+            raise ValueError(
+                "No supported normalization function for distance"
+                f" metric of type: {distance}.Consider providing"
+                " relevance_score_fn to Chroma constructor."
+            )
+
+    def max_marginal_relevance_search_by_vector(
+        self,
+        embedding: List[float],
+        k: int = DEFAULT_K,
+        fetch_k: int = 20,
+        lambda_mult: float = 0.5,
+        filter: Optional[Dict[str, str]] = None,
+        where_document: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Document]:
+        """Return docs selected using the maximal marginal relevance.
+        Maximal marginal relevance optimizes for similarity to query AND diversity
+        among selected documents.
+
+        Args:
+            embedding: Embedding to look up documents similar to.
+            k: Number of Documents to return. Defaults to 4.
+            fetch_k: Number of Documents to fetch to pass to MMR algorithm.
+            lambda_mult: Number between 0 and 1 that determines the degree
+                        of diversity among the results with 0 corresponding
+                        to maximum diversity and 1 to minimum diversity.
+                        Defaults to 0.5.
+            filter (Optional[Dict[str, str]]): Filter by metadata. Defaults to None.
+
+        Returns:
+            List of Documents selected by maximal marginal relevance.
+        """
+
+        results = self.__query_collection(
+            query_embeddings=embedding,
+            n_results=fetch_k,
+            where=filter,
+            where_document=where_document,
+            include=[
+                "metadatas",
+                "documents",
+                "distances",
+                "embeddings",
+            ],
+        )
+        mmr_selected = maximal_marginal_relevance(
+            np.array(embedding, dtype=np.float32),
+            results["embeddings"][0],
+            k=k,
+            lambda_mult=lambda_mult,
+        )
+
+        candidates = _results_to_docs(results)
+
+        selected_results = [
+            r for i, r in enumerate(candidates) if i in mmr_selected
+        ]
+        return selected_results
+
+    def max_marginal_relevance_search(
+        self,
+        query: str,
+        k: int = DEFAULT_K,
+        fetch_k: int = 20,
+        lambda_mult: float = 0.5,
+        filter: Optional[Dict[str, str]] = None,
+        where_document: Optional[Dict[str, str]] = None,
+        **kwargs: Any,
+    ) -> List[Document]:
+        """Return docs selected using the maximal marginal relevance.
+        Maximal marginal relevance optimizes for similarity to query AND diversity
+        among selected documents.
+
+        Args:
+            query: Text to look up documents similar to.
+            k: Number of Documents to return. Defaults to 4.
+            fetch_k: Number of Documents to fetch to pass to MMR algorithm.
+            lambda_mult: Number between 0 and 1 that determines the degree
+                        of diversity among the results with 0 corresponding
+                        to maximum diversity and 1 to minimum diversity.
+                        Defaults to 0.5.
+            filter (Optional[Dict[str, str]]): Filter by metadata. Defaults to None.
+
+        Returns:
+            List of Documents selected by maximal marginal relevance.
+        """
+        if self._embedding_function is None:
+            raise ValueError(
+                "For MMR search, you must specify an embedding"
+                " function oncreation."
+            )
+
+        embedding = self._embedding_function.embed_query(query)
+        docs = self.max_marginal_relevance_search_by_vector(
+            embedding,
+            k,
+            fetch_k,
+            lambda_mult=lambda_mult,
+            filter=filter,
+            where_document=where_document,
+        )
+        return docs
+
+    def delete_collection(self) -> None:
+        """Delete the collection."""
+        self._client.delete_collection(self._collection.name)
+
+    def get(
+        self,
+        ids: Optional[OneOrMany[ID]] = None,
+        where: Optional[Where] = None,
+        limit: Optional[int] = None,
+        offset: Optional[int] = None,
+        where_document: Optional[WhereDocument] = None,
+        include: Optional[List[str]] = None,
+    ) -> Dict[str, Any]:
+        """Gets the collection.
+
+        Args:
+            ids: The ids of the embeddings to get. Optional.
+            where: A Where type dict used to filter results by.
+                   E.g. `{"color" : "red", "price": 4.20}`. Optional.
+            limit: The number of documents to return. Optional.
+            offset: The offset to start returning results from.
+                    Useful for paging results with limit. Optional.
+            where_document: A WhereDocument type dict used to filter by the documents.
+                            E.g. `{$contains: "hello"}`. Optional.
+            include: A list of what to include in the results.
+                     Can contain `"embeddings"`, `"metadatas"`, `"documents"`.
+                     Ids are always included.
+                     Defaults to `["metadatas", "documents"]`. Optional.
+        """
+        kwargs = {
+            "ids": ids,
+            "where": where,
+            "limit": limit,
+            "offset": offset,
+            "where_document": where_document,
+        }
+
+        if include is not None:
+            kwargs["include"] = include
+
+        return self._collection.get(**kwargs)
+
+    def persist(self) -> None:
+        """Persist the collection.
+
+        This can be used to explicitly persist the data to disk.
+        It will also be called automatically when the object is destroyed.
+        """
+        if self._persist_directory is None:
+            raise ValueError(
+                "You must specify a persist_directory on"
+                "creation to persist the collection."
+            )
+        import chromadb
+
+        # Maintain backwards compatibility with chromadb < 0.4.0
+        major, minor, _ = chromadb.__version__.split(".")
+        if int(major) == 0 and int(minor) < 4:
+            self._client.persist()
+
+    def update_document(
+        self, document_id: str, document: Document
+    ) -> None:
+        """Update a document in the collection.
+
+        Args:
+            document_id (str): ID of the document to update.
+            document (Document): Document to update.
+        """
+        return self.update_documents([document_id], [document])
+
+    def update_documents(
+        self, ids: List[str], documents: List[Document]
+    ) -> None:
+        """Update a document in the collection.
+
+        Args:
+            ids (List[str]): List of ids of the document to update.
+            documents (List[Document]): List of documents to update.
+        """
+        text = [document.page_content for document in documents]
+        metadata = [document.metadata for document in documents]
+        if self._embedding_function is None:
+            raise ValueError(
+                "For update, you must specify an embedding function"
+                " on creation."
+            )
+        embeddings = self._embedding_function.embed_documents(text)
+
+        if hasattr(
+            self._collection._client, "max_batch_size"
+        ):  # for Chroma 0.4.10 and above
+            from chromadb.utils.batch_utils import create_batches
+
+            for batch in create_batches(
+                api=self._collection._client,
+                ids=ids,
+                metadatas=metadata,
+                documents=text,
+                embeddings=embeddings,
+            ):
+                self._collection.update(
+                    ids=batch[0],
+                    embeddings=batch[1],
+                    documents=batch[3],
+                    metadatas=batch[2],
+                )
+        else:
+            self._collection.update(
+                ids=ids,
+                embeddings=embeddings,
+                documents=text,
+                metadatas=metadata,
+            )
+
+    @classmethod
+    def from_texts(
+        cls: Type[Chroma],
+        texts: List[str],
+        embedding: Optional[Embeddings] = None,
+        metadatas: Optional[List[dict]] = None,
+        ids: Optional[List[str]] = None,
+        collection_name: str = _LANGCHAIN_DEFAULT_COLLECTION_NAME,
+        persist_directory: Optional[str] = None,
+        client_settings: Optional[chromadb.config.Settings] = None,
+        client: Optional[chromadb.Client] = None,
+        collection_metadata: Optional[Dict] = None,
+        **kwargs: Any,
+    ) -> Chroma:
+        """Create a Chroma vectorstore from a raw documents.
+
+        If a persist_directory is specified, the collection will be persisted there.
+        Otherwise, the data will be ephemeral in-memory.
+
+        Args:
+            texts (List[str]): List of texts to add to the collection.
+            collection_name (str): Name of the collection to create.
+            persist_directory (Optional[str]): Directory to persist the collection.
+            embedding (Optional[Embeddings]): Embedding function. Defaults to None.
+            metadatas (Optional[List[dict]]): List of metadatas. Defaults to None.
+            ids (Optional[List[str]]): List of document IDs. Defaults to None.
+            client_settings (Optional[chromadb.config.Settings]): Chroma client settings
+            collection_metadata (Optional[Dict]): Collection configurations.
+                                                  Defaults to None.
+
+        Returns:
+            Chroma: Chroma vectorstore.
+        """
+        chroma_collection = cls(
+            collection_name=collection_name,
+            embedding_function=embedding,
+            persist_directory=persist_directory,
+            client_settings=client_settings,
+            client=client,
+            collection_metadata=collection_metadata,
+            **kwargs,
+        )
+        if ids is None:
+            ids = [str(uuid.uuid1()) for _ in texts]
+        if hasattr(
+            chroma_collection._client, "max_batch_size"
+        ):  # for Chroma 0.4.10 and above
+            from chromadb.utils.batch_utils import create_batches
+
+            for batch in create_batches(
+                api=chroma_collection._client,
+                ids=ids,
+                metadatas=metadatas,
+                documents=texts,
+            ):
+                chroma_collection.add_texts(
+                    texts=batch[3] if batch[3] else [],
+                    metadatas=batch[2] if batch[2] else None,
+                    ids=batch[0],
+                )
+        else:
+            chroma_collection.add_texts(
+                texts=texts, metadatas=metadatas, ids=ids
+            )
+        return chroma_collection
+
+    @classmethod
+    def from_documents(
+        cls: Type[Chroma],
+        documents: List[Document],
+        embedding: Optional[Embeddings] = None,
+        ids: Optional[List[str]] = None,
+        collection_name: str = _LANGCHAIN_DEFAULT_COLLECTION_NAME,
+        persist_directory: Optional[str] = None,
+        client_settings: Optional[chromadb.config.Settings] = None,
+        client: Optional[chromadb.Client] = None,  # Add this line
+        collection_metadata: Optional[Dict] = None,
+        **kwargs: Any,
+    ) -> Chroma:
+        """Create a Chroma vectorstore from a list of documents.
+
+        If a persist_directory is specified, the collection will be persisted there.
+        Otherwise, the data will be ephemeral in-memory.
+
+        Args:
+            collection_name (str): Name of the collection to create.
+            persist_directory (Optional[str]): Directory to persist the collection.
+            ids (Optional[List[str]]): List of document IDs. Defaults to None.
+            documents (List[Document]): List of documents to add to the vectorstore.
+            embedding (Optional[Embeddings]): Embedding function. Defaults to None.
+            client_settings (Optional[chromadb.config.Settings]): Chroma client settings
+            collection_metadata (Optional[Dict]): Collection configurations.
+                                                  Defaults to None.
+
+        Returns:
+            Chroma: Chroma vectorstore.
+        """
+        texts = [doc.page_content for doc in documents]
+        metadatas = [doc.metadata for doc in documents]
+        return cls.from_texts(
+            texts=texts,
+            embedding=embedding,
+            metadatas=metadatas,
+            ids=ids,
+            collection_name=collection_name,
+            persist_directory=persist_directory,
+            client_settings=client_settings,
+            client=client,
+            collection_metadata=collection_metadata,
+            **kwargs,
+        )
+
+    def delete(
+        self, ids: Optional[List[str]] = None, **kwargs: Any
+    ) -> None:
+        """Delete by vector IDs.
+
+        Args:
+            ids: List of ids to delete.
+        """
+        self._collection.delete(ids=ids)
diff --git a/swarms/memory/chroma_db.py b/swarms/memory/chroma_db.py
new file mode 100644
index 00000000..a225524e
--- /dev/null
+++ b/swarms/memory/chroma_db.py
@@ -0,0 +1,172 @@
+import os
+from termcolor import colored
+import logging
+from typing import Dict, List, Optional
+import chromadb
+import tiktoken as tiktoken
+from chromadb.config import Settings
+from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
+from dotenv import load_dotenv
+from swarms.utils.token_count_tiktoken import limit_tokens_from_string
+
+load_dotenv()
+
+# ChromaDB settings
+client = chromadb.Client(Settings(anonymized_telemetry=False))
+
+
+# ChromaDB client
+def get_chromadb_client():
+    return client
+
+
+#  OpenAI API key
+OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
+
+
+# Results storage using local ChromaDB
+class ChromaDB:
+    """
+
+    ChromaDB database
+
+    Args:
+        metric (str): _description_
+        RESULTS_STORE_NAME (str): _description_
+        LLM_MODEL (str): _description_
+        openai_api_key (str): _description_
+
+    Methods:
+        add: _description_
+        query: _description_
+
+    Examples:
+        >>> chromadb = ChromaDB(
+        >>>     metric="cosine",
+        >>>     RESULTS_STORE_NAME="results",
+        >>>     LLM_MODEL="gpt3",
+        >>>     openai_api_key=OPENAI_API_KEY,
+        >>> )
+        >>> chromadb.add(task, result, result_id)
+        >>> chromadb.query(query, top_results_num)
+    """
+
+    def __init__(
+        self,
+        metric: str,
+        RESULTS_STORE_NAME: str,
+        LLM_MODEL: str,
+        openai_api_key: str = OPENAI_API_KEY,
+        top_results_num: int = 3,
+        limit_tokens: Optional[int] = 1000,
+    ):
+        self.metric = metric
+        self.RESULTS_STORE_NAME = RESULTS_STORE_NAME
+        self.LLM_MODEL = LLM_MODEL
+        self.openai_api_key = openai_api_key
+        self.top_results_num = top_results_num
+        self.limit_tokens = limit_tokens
+
+        # Disable ChromaDB logging
+        logging.getLogger("chromadb").setLevel(logging.ERROR)
+        # Create Chroma collection
+        chroma_persist_dir = "chroma"
+        chroma_client = chromadb.PersistentClient(
+            settings=chromadb.config.Settings(
+                persist_directory=chroma_persist_dir,
+            )
+        )
+
+        # Create embedding function
+        embedding_function = OpenAIEmbeddingFunction(
+            api_key=openai_api_key
+        )
+
+        # Create Chroma collection
+        self.collection = chroma_client.get_or_create_collection(
+            name=RESULTS_STORE_NAME,
+            metadata={"hnsw:space": metric},
+            embedding_function=embedding_function,
+        )
+
+    def add(self, task: Dict, result: str, result_id: str):
+        """Adds a result to the ChromaDB collection
+
+        Args:
+            task (Dict): _description_
+            result (str): _description_
+            result_id (str): _description_
+        """
+
+        try:
+            # Embed the result
+            embeddings = (
+                self.collection.embedding_function.embed([result])[0]
+                .tolist()
+                .copy()
+            )
+
+            # If the result is a list, flatten it
+            if (
+                len(
+                    self.collection.get(ids=[result_id], include=[])[
+                        "ids"
+                    ]
+                )
+                > 0
+            ):  # Check if the result already exists
+                self.collection.update(
+                    ids=result_id,
+                    embeddings=embeddings,
+                    documents=result,
+                    metadatas={
+                        "task": task["task_name"],
+                        "result": result,
+                    },
+                )
+
+            # If the result is not a list, add it
+            else:
+                self.collection.add(
+                    ids=result_id,
+                    embeddings=embeddings,
+                    documents=result,
+                    metadatas={
+                        "task": task["task_name"],
+                        "result": result,
+                    },
+                )
+        except Exception as error:
+            print(
+                colored(f"Error adding to ChromaDB: {error}", "red")
+            )
+
+    def query(
+        self,
+        query: str,
+    ) -> List[dict]:
+        """Queries the ChromaDB collection with a query for the top results
+
+        Args:
+            query (str): _description_
+            top_results_num (int): _description_
+
+        Returns:
+            List[dict]: _description_
+        """
+        try:
+            count: int = self.collection.count()
+            if count == 0:
+                return []
+            results = self.collection.query(
+                query_texts=query,
+                n_results=min(self.top_results_num, count),
+                include=["metadatas"],
+            )
+            out = [item["task"] for item in results["metadatas"][0]]
+            out = limit_tokens_from_string(
+                out, "gpt-4", self.limit_tokens
+            )
+            return out
+        except Exception as error:
+            print(colored(f"Error querying ChromaDB: {error}", "red"))
diff --git a/swarms/memory/cosine_similarity.py b/swarms/memory/cosine_similarity.py
index 99d47368..6e7b1df3 100644
--- a/swarms/memory/cosine_similarity.py
+++ b/swarms/memory/cosine_similarity.py
@@ -18,8 +18,8 @@ def cosine_similarity(X: Matrix, Y: Matrix) -> np.ndarray:
     Y = np.array(Y)
     if X.shape[1] != Y.shape[1]:
         raise ValueError(
-            f"Number of columns in X and Y must be the same. X has shape {X.shape} "
-            f"and Y has shape {Y.shape}."
+            "Number of columns in X and Y must be the same. X has"
+            f" shape {X.shape} and Y has shape {Y.shape}."
         )
     try:
         import simsimd as simd
@@ -32,8 +32,9 @@ def cosine_similarity(X: Matrix, Y: Matrix) -> np.ndarray:
         return Z
     except ImportError:
         logger.info(
-            "Unable to import simsimd, defaulting to NumPy implementation. If you want "
-            "to use simsimd please install with `pip install simsimd`."
+            "Unable to import simsimd, defaulting to NumPy"
+            " implementation. If you want to use simsimd please"
+            " install with `pip install simsimd`."
         )
         X_norm = np.linalg.norm(X, axis=1)
         Y_norm = np.linalg.norm(Y, axis=1)
@@ -67,9 +68,15 @@ def cosine_similarity_top_k(
     score_array = cosine_similarity(X, Y)
     score_threshold = score_threshold or -1.0
     score_array[score_array < score_threshold] = 0
-    top_k = min(top_k or len(score_array), np.count_nonzero(score_array))
-    top_k_idxs = np.argpartition(score_array, -top_k, axis=None)[-top_k:]
-    top_k_idxs = top_k_idxs[np.argsort(score_array.ravel()[top_k_idxs])][::-1]
+    top_k = min(
+        top_k or len(score_array), np.count_nonzero(score_array)
+    )
+    top_k_idxs = np.argpartition(score_array, -top_k, axis=None)[
+        -top_k:
+    ]
+    top_k_idxs = top_k_idxs[
+        np.argsort(score_array.ravel()[top_k_idxs])
+    ][::-1]
     ret_idxs = np.unravel_index(top_k_idxs, score_array.shape)
     scores = score_array.ravel()[top_k_idxs].tolist()
     return list(zip(*ret_idxs)), scores  # type: ignore
diff --git a/swarms/memory/db.py b/swarms/memory/db.py
deleted file mode 100644
index 9f23b59f..00000000
--- a/swarms/memory/db.py
+++ /dev/null
@@ -1,175 +0,0 @@
-import uuid
-from abc import ABC
-from typing import Any, Dict, List, Optional
-
-from swarms.memory.schemas import Artifact, Status
-from swarms.memory.schemas import Step as APIStep
-from swarms.memory.schemas import Task as APITask
-
-
-class Step(APIStep):
-    additional_properties: Optional[Dict[str, str]] = None
-
-
-class Task(APITask):
-    steps: List[Step] = []
-
-
-class NotFoundException(Exception):
-    """
-    Exception raised when a resource is not found.
-    """
-
-    def __init__(self, item_name: str, item_id: str):
-        self.item_name = item_name
-        self.item_id = item_id
-        super().__init__(f"{item_name} with {item_id} not found.")
-
-
-class TaskDB(ABC):
-    async def create_task(
-        self,
-        input: Optional[str],
-        additional_input: Any = None,
-        artifacts: Optional[List[Artifact]] = None,
-        steps: Optional[List[Step]] = None,
-    ) -> Task:
-        raise NotImplementedError
-
-    async def create_step(
-        self,
-        task_id: str,
-        name: Optional[str] = None,
-        input: Optional[str] = None,
-        is_last: bool = False,
-        additional_properties: Optional[Dict[str, str]] = None,
-    ) -> Step:
-        raise NotImplementedError
-
-    async def create_artifact(
-        self,
-        task_id: str,
-        file_name: str,
-        relative_path: Optional[str] = None,
-        step_id: Optional[str] = None,
-    ) -> Artifact:
-        raise NotImplementedError
-
-    async def get_task(self, task_id: str) -> Task:
-        raise NotImplementedError
-
-    async def get_step(self, task_id: str, step_id: str) -> Step:
-        raise NotImplementedError
-
-    async def get_artifact(self, task_id: str, artifact_id: str) -> Artifact:
-        raise NotImplementedError
-
-    async def list_tasks(self) -> List[Task]:
-        raise NotImplementedError
-
-    async def list_steps(
-        self, task_id: str, status: Optional[Status] = None
-    ) -> List[Step]:
-        raise NotImplementedError
-
-
-class InMemoryTaskDB(TaskDB):
-    _tasks: Dict[str, Task] = {}
-
-    async def create_task(
-        self,
-        input: Optional[str],
-        additional_input: Any = None,
-        artifacts: Optional[List[Artifact]] = None,
-        steps: Optional[List[Step]] = None,
-    ) -> Task:
-        if not steps:
-            steps = []
-        if not artifacts:
-            artifacts = []
-        task_id = str(uuid.uuid4())
-        task = Task(
-            task_id=task_id,
-            input=input,
-            steps=steps,
-            artifacts=artifacts,
-            additional_input=additional_input,
-        )
-        self._tasks[task_id] = task
-        return task
-
-    async def create_step(
-        self,
-        task_id: str,
-        name: Optional[str] = None,
-        input: Optional[str] = None,
-        is_last=False,
-        additional_properties: Optional[Dict[str, Any]] = None,
-    ) -> Step:
-        step_id = str(uuid.uuid4())
-        step = Step(
-            task_id=task_id,
-            step_id=step_id,
-            name=name,
-            input=input,
-            status=Status.created,
-            is_last=is_last,
-            additional_properties=additional_properties,
-        )
-        task = await self.get_task(task_id)
-        task.steps.append(step)
-        return step
-
-    async def get_task(self, task_id: str) -> Task:
-        task = self._tasks.get(task_id, None)
-        if not task:
-            raise NotFoundException("Task", task_id)
-        return task
-
-    async def get_step(self, task_id: str, step_id: str) -> Step:
-        task = await self.get_task(task_id)
-        step = next(filter(lambda s: s.task_id == task_id, task.steps), None)
-        if not step:
-            raise NotFoundException("Step", step_id)
-        return step
-
-    async def get_artifact(self, task_id: str, artifact_id: str) -> Artifact:
-        task = await self.get_task(task_id)
-        artifact = next(
-            filter(lambda a: a.artifact_id == artifact_id, task.artifacts), None
-        )
-        if not artifact:
-            raise NotFoundException("Artifact", artifact_id)
-        return artifact
-
-    async def create_artifact(
-        self,
-        task_id: str,
-        file_name: str,
-        relative_path: Optional[str] = None,
-        step_id: Optional[str] = None,
-    ) -> Artifact:
-        artifact_id = str(uuid.uuid4())
-        artifact = Artifact(
-            artifact_id=artifact_id, file_name=file_name, relative_path=relative_path
-        )
-        task = await self.get_task(task_id)
-        task.artifacts.append(artifact)
-
-        if step_id:
-            step = await self.get_step(task_id, step_id)
-            step.artifacts.append(artifact)
-
-        return artifact
-
-    async def list_tasks(self) -> List[Task]:
-        return [task for task in self._tasks.values()]
-
-    async def list_steps(
-        self, task_id: str, status: Optional[Status] = None
-    ) -> List[Step]:
-        task = await self.get_task(task_id)
-        steps = task.steps
-        if status:
-            steps = list(filter(lambda s: s.status == status, steps))
-        return steps
diff --git a/swarms/memory/ocean.py b/swarms/memory/ocean.py
deleted file mode 100644
index da58c81c..00000000
--- a/swarms/memory/ocean.py
+++ /dev/null
@@ -1,153 +0,0 @@
-import logging
-from typing import List
-
-import oceandb
-from oceandb.utils.embedding_function import MultiModalEmbeddingFunction
-
-
-class OceanDB:
-    """
-    A class to interact with OceanDB.
-
-    ...
-
-    Attributes
-    ----------
-    client : oceandb.Client
-        a client to interact with OceanDB
-
-    Methods
-    -------
-    create_collection(collection_name: str, modality: str):
-        Creates a new collection in OceanDB.
-    append_document(collection, document: str, id: str):
-        Appends a document to a collection in OceanDB.
-    add_documents(collection, documents: List[str], ids: List[str]):
-        Adds multiple documents to a collection in OceanDB.
-    query(collection, query_texts: list[str], n_results: int):
-        Queries a collection in OceanDB.
-    """
-
-    def __init__(self, client: oceandb.Client = None):
-        """
-        Constructs all the necessary attributes for the OceanDB object.
-
-        Parameters
-        ----------
-            client : oceandb.Client, optional
-                a client to interact with OceanDB (default is None, which creates a new client)
-        """
-        try:
-            self.client = client if client else oceandb.Client()
-            print(self.client.heartbeat())
-        except Exception as e:
-            logging.error(f"Failed to initialize OceanDB client. Error: {e}")
-            raise
-
-    def create_collection(self, collection_name: str, modality: str):
-        """
-        Creates a new collection in OceanDB.
-
-        Parameters
-        ----------
-            collection_name : str
-                the name of the new collection
-            modality : str
-                the modality of the new collection
-
-        Returns
-        -------
-            collection
-                the created collection
-        """
-        try:
-            embedding_function = MultiModalEmbeddingFunction(modality=modality)
-            collection = self.client.create_collection(
-                collection_name, embedding_function=embedding_function
-            )
-            return collection
-        except Exception as e:
-            logging.error(f"Failed to create collection. Error {e}")
-            raise
-
-    def append_document(self, collection, document: str, id: str):
-        """
-        Appends a document to a collection in OceanDB.
-
-        Parameters
-        ----------
-            collection
-                the collection to append the document to
-            document : str
-                the document to append
-            id : str
-                the id of the document
-
-        Returns
-        -------
-            result
-                the result of the append operation
-        """
-        try:
-            return collection.add(documents=[document], ids=[id])
-        except Exception as e:
-            logging.error(f"Failed to append document to the collection. Error {e}")
-            raise
-
-    def add_documents(self, collection, documents: List[str], ids: List[str]):
-        """
-        Adds multiple documents to a collection in OceanDB.
-
-        Parameters
-        ----------
-            collection
-                the collection to add the documents to
-            documents : List[str]
-                the documents to add
-            ids : List[str]
-                the ids of the documents
-
-        Returns
-        -------
-            result
-                the result of the add operation
-        """
-        try:
-            return collection.add(documents=documents, ids=ids)
-        except Exception as e:
-            logging.error(f"Failed to add documents to collection. Error: {e}")
-            raise
-
-    def query(self, collection, query_texts: list[str], n_results: int):
-        """
-        Queries a collection in OceanDB.
-
-        Parameters
-        ----------
-            collection
-                the collection to query
-            query_texts : list[str]
-                the texts to query
-            n_results : int
-                the number of results to return
-
-        Returns
-        -------
-            results
-                the results of the query
-        """
-        try:
-            results = collection.query(query_texts=query_texts, n_results=n_results)
-            return results
-        except Exception as e:
-            logging.error(f"Failed to query the collection. Error {e}")
-            raise
-
-
-# Example
-# ocean = OceanDB()
-# collection = ocean.create_collection("test", "text")
-# ocean.append_document(collection, "hello world", "1")
-# ocean.add_documents(collection, ["hello world", "hello world"], ["2", "3"])
-# results = ocean.query(collection, ["hello world"], 3)
-# print(results)
diff --git a/swarms/memory/pg.py b/swarms/memory/pg.py
index a421c887..334ccf70 100644
--- a/swarms/memory/pg.py
+++ b/swarms/memory/pg.py
@@ -84,27 +84,36 @@ class PgVectorVectorStore(BaseVectorStore):
 
     """
 
-    connection_string: Optional[str] = field(default=None, kw_only=True)
+    connection_string: Optional[str] = field(
+        default=None, kw_only=True
+    )
     create_engine_params: dict = field(factory=dict, kw_only=True)
     engine: Optional[Engine] = field(default=None, kw_only=True)
     table_name: str = field(kw_only=True)
     _model: any = field(
-        default=Factory(lambda self: self.default_vector_model(), takes_self=True)
+        default=Factory(
+            lambda self: self.default_vector_model(), takes_self=True
+        )
     )
 
     @connection_string.validator
-    def validate_connection_string(self, _, connection_string: Optional[str]) -> None:
+    def validate_connection_string(
+        self, _, connection_string: Optional[str]
+    ) -> None:
         # If an engine is provided, the connection string is not used.
         if self.engine is not None:
             return
 
         # If an engine is not provided, a connection string is required.
         if connection_string is None:
-            raise ValueError("An engine or connection string is required")
+            raise ValueError(
+                "An engine or connection string is required"
+            )
 
         if not connection_string.startswith("postgresql://"):
             raise ValueError(
-                "The connection string must describe a Postgres database connection"
+                "The connection string must describe a Postgres"
+                " database connection"
             )
 
     @engine.validator
@@ -115,7 +124,9 @@ class PgVectorVectorStore(BaseVectorStore):
 
         # If a connection string is not provided, an engine is required.
         if engine is None:
-            raise ValueError("An engine or connection string is required")
+            raise ValueError(
+                "An engine or connection string is required"
+            )
 
     def __attrs_post_init__(self) -> None:
         """If a an engine is provided, it will be used to connect to the database.
@@ -134,10 +145,14 @@ class PgVectorVectorStore(BaseVectorStore):
     ) -> None:
         """Provides a mechanism to initialize the database schema and extensions."""
         if install_uuid_extension:
-            self.engine.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";')
+            self.engine.execute(
+                'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'
+            )
 
         if install_vector_extension:
-            self.engine.execute('CREATE EXTENSION IF NOT EXISTS "vector";')
+            self.engine.execute(
+                'CREATE EXTENSION IF NOT EXISTS "vector";'
+            )
 
         if create_schema:
             self._model.metadata.create_all(self.engine)
@@ -148,7 +163,7 @@ class PgVectorVectorStore(BaseVectorStore):
         vector_id: Optional[str] = None,
         namespace: Optional[str] = None,
         meta: Optional[dict] = None,
-        **kwargs
+        **kwargs,
     ) -> str:
         """Inserts or updates a vector in the collection."""
         with Session(self.engine) as session:
@@ -208,7 +223,7 @@ class PgVectorVectorStore(BaseVectorStore):
         namespace: Optional[str] = None,
         include_vectors: bool = False,
         distance_metric: str = "cosine_distance",
-        **kwargs
+        **kwargs,
     ) -> list[BaseVectorStore.QueryResult]:
         """Performs a search on the collection to find vectors similar to the provided input vector,
         optionally filtering to only those that match the provided namespace.
@@ -241,7 +256,9 @@ class PgVectorVectorStore(BaseVectorStore):
             return [
                 BaseVectorStore.QueryResult(
                     id=str(result[0].id),
-                    vector=result[0].vector if include_vectors else None,
+                    vector=(
+                        result[0].vector if include_vectors else None
+                    ),
                     score=result[1],
                     meta=result[0].meta,
                     namespace=result[0].namespace,
diff --git a/swarms/memory/pinecone.py b/swarms/memory/pinecone.py
index 2374f12a..308273d9 100644
--- a/swarms/memory/pinecone.py
+++ b/swarms/memory/pinecone.py
@@ -1,12 +1,12 @@
 from typing import Optional
-from swarms.memory.vector_stores.base import BaseVector
+from swarms.memory.base import BaseVectorStore
 import pinecone
 from attr import define, field
 from swarms.utils.hash import str_to_hash
 
 
 @define
-class PineconeVectorStoreStore(BaseVector):
+class PineconeVectorStoreStore(BaseVectorStore):
     """
     PineconeVectorStore is a vector storage driver that uses Pinecone as the underlying storage engine.
 
@@ -24,11 +24,11 @@ class PineconeVectorStoreStore(BaseVector):
     Methods:
         upsert_vector(vector: list[float], vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, **kwargs) -> str:
             Upserts a vector into the index.
-        load_entry(vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVector.Entry]:
+        load_entry(vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStore.Entry]:
             Loads a single vector from the index.
-        load_entries(namespace: Optional[str] = None) -> list[BaseVector.Entry]:
+        load_entries(namespace: Optional[str] = None) -> list[BaseVectorStore.Entry]:
             Loads all vectors from the index.
-        query(query: str, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, include_metadata=True, **kwargs) -> list[BaseVector.QueryResult]:
+        query(query: str, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, include_metadata=True, **kwargs) -> list[BaseVectorStore.QueryResult]:
             Queries the index for vectors similar to the given query string.
         create_index(name: str, **kwargs) -> None:
             Creates a new index.
@@ -108,10 +108,12 @@ class PineconeVectorStoreStore(BaseVector):
         vector_id: Optional[str] = None,
         namespace: Optional[str] = None,
         meta: Optional[dict] = None,
-        **kwargs
+        **kwargs,
     ) -> str:
         """Upsert vector"""
-        vector_id = vector_id if vector_id else str_to_hash(str(vector))
+        vector_id = (
+            vector_id if vector_id else str_to_hash(str(vector))
+        )
 
         params = {"namespace": namespace} | kwargs
 
@@ -121,15 +123,17 @@ class PineconeVectorStoreStore(BaseVector):
 
     def load_entry(
         self, vector_id: str, namespace: Optional[str] = None
-    ) -> Optional[BaseVector.Entry]:
+    ) -> Optional[BaseVectorStore.Entry]:
         """Load entry"""
-        result = self.index.fetch(ids=[vector_id], namespace=namespace).to_dict()
+        result = self.index.fetch(
+            ids=[vector_id], namespace=namespace
+        ).to_dict()
         vectors = list(result["vectors"].values())
 
         if len(vectors) > 0:
             vector = vectors[0]
 
-            return BaseVector.Entry(
+            return BaseVectorStore.Entry(
                 id=vector["id"],
                 meta=vector["metadata"],
                 vector=vector["values"],
@@ -138,7 +142,9 @@ class PineconeVectorStoreStore(BaseVector):
         else:
             return None
 
-    def load_entries(self, namespace: Optional[str] = None) -> list[BaseVector.Entry]:
+    def load_entries(
+        self, namespace: Optional[str] = None
+    ) -> list[BaseVectorStore.Entry]:
         """Load entries"""
         # This is a hacky way to query up to 10,000 values from Pinecone. Waiting on an official API for fetching
         # all values from a namespace:
@@ -152,7 +158,7 @@ class PineconeVectorStoreStore(BaseVector):
         )
 
         return [
-            BaseVector.Entry(
+            BaseVectorStore.Entry(
                 id=r["id"],
                 vector=r["values"],
                 meta=r["metadata"],
@@ -169,13 +175,17 @@ class PineconeVectorStoreStore(BaseVector):
         include_vectors: bool = False,
         # PineconeVectorStoreStorageDriver-specific params:
         include_metadata=True,
-        **kwargs
-    ) -> list[BaseVector.QueryResult]:
+        **kwargs,
+    ) -> list[BaseVectorStore.QueryResult]:
         """Query vectors"""
         vector = self.embedding_driver.embed_string(query)
 
         params = {
-            "top_k": count if count else BaseVector.DEFAULT_QUERY_COUNT,
+            "top_k": (
+                count
+                if count
+                else BaseVectorStore.DEFAULT_QUERY_COUNT
+            ),
             "namespace": namespace,
             "include_values": include_vectors,
             "include_metadata": include_metadata,
@@ -184,7 +194,7 @@ class PineconeVectorStoreStore(BaseVector):
         results = self.index.query(vector, **params)
 
         return [
-            BaseVector.QueryResult(
+            BaseVectorStore.QueryResult(
                 id=r["id"],
                 vector=r["values"],
                 score=r["score"],
@@ -196,6 +206,9 @@ class PineconeVectorStoreStore(BaseVector):
 
     def create_index(self, name: str, **kwargs) -> None:
         """Create index"""
-        params = {"name": name, "dimension": self.embedding_driver.dimensions} | kwargs
+        params = {
+            "name": name,
+            "dimension": self.embedding_driver.dimensions,
+        } | kwargs
 
         pinecone.create_index(**params)
diff --git a/swarms/memory/qdrant.py b/swarms/memory/qdrant.py
index 7bc5018e..76a5785b 100644
--- a/swarms/memory/qdrant.py
+++ b/swarms/memory/qdrant.py
@@ -1,6 +1,145 @@
-"""
-QDRANT MEMORY CLASS
+from typing import List
+from sentence_transformers import SentenceTransformer
+from httpx import RequestError
+from qdrant_client import QdrantClient
+from qdrant_client.http.models import (
+    Distance,
+    VectorParams,
+    PointStruct,
+)
 
 
+class Qdrant:
+    """
+    Qdrant class for managing collections and performing vector operations using QdrantClient.
 
-"""
+    Attributes:
+        client (QdrantClient): The Qdrant client for interacting with the Qdrant server.
+        collection_name (str): Name of the collection to be managed in Qdrant.
+        model (SentenceTransformer): The model used for generating sentence embeddings.
+
+    Args:
+        api_key (str): API key for authenticating with Qdrant.
+        host (str): Host address of the Qdrant server.
+        port (int): Port number of the Qdrant server. Defaults to 6333.
+        collection_name (str): Name of the collection to be used or created. Defaults to "qdrant".
+        model_name (str): Name of the model to be used for embeddings. Defaults to "BAAI/bge-small-en-v1.5".
+        https (bool): Flag to indicate if HTTPS should be used. Defaults to True.
+    """
+
+    def __init__(
+        self,
+        api_key: str,
+        host: str,
+        port: int = 6333,
+        collection_name: str = "qdrant",
+        model_name: str = "BAAI/bge-small-en-v1.5",
+        https: bool = True,
+    ):
+        try:
+            self.client = QdrantClient(
+                url=host, port=port, api_key=api_key
+            )
+            self.collection_name = collection_name
+            self._load_embedding_model(model_name)
+            self._setup_collection()
+        except RequestError as e:
+            print(f"Error setting up QdrantClient: {e}")
+
+    def _load_embedding_model(self, model_name: str):
+        """
+        Loads the sentence embedding model specified by the model name.
+
+        Args:
+            model_name (str): The name of the model to load for generating embeddings.
+        """
+        try:
+            self.model = SentenceTransformer(model_name)
+        except Exception as e:
+            print(f"Error loading embedding model: {e}")
+
+    def _setup_collection(self):
+        try:
+            exists = self.client.get_collection(self.collection_name)
+            if exists:
+                print(
+                    f"Collection '{self.collection_name}' already"
+                    " exists."
+                )
+        except Exception as e:
+            self.client.create_collection(
+                collection_name=self.collection_name,
+                vectors_config=VectorParams(
+                    size=self.model.get_sentence_embedding_dimension(),
+                    distance=Distance.DOT,
+                ),
+            )
+            print(f"Collection '{self.collection_name}' created.")
+
+    def add_vectors(self, docs: List[dict]):
+        """
+        Adds vector representations of documents to the Qdrant collection.
+
+        Args:
+            docs (List[dict]): A list of documents where each document is a dictionary with at least a 'page_content' key.
+
+        Returns:
+            OperationResponse or None: Returns the operation information if successful, otherwise None.
+        """
+        points = []
+        for i, doc in enumerate(docs):
+            try:
+                if "page_content" in doc:
+                    embedding = self.model.encode(
+                        doc["page_content"], normalize_embeddings=True
+                    )
+                    points.append(
+                        PointStruct(
+                            id=i + 1,
+                            vector=embedding,
+                            payload={"content": doc["page_content"]},
+                        )
+                    )
+                else:
+                    print(
+                        f"Document at index {i} is missing"
+                        " 'page_content' key"
+                    )
+            except Exception as e:
+                print(f"Error processing document at index {i}: {e}")
+
+        try:
+            operation_info = self.client.upsert(
+                collection_name=self.collection_name,
+                wait=True,
+                points=points,
+            )
+            return operation_info
+        except Exception as e:
+            print(f"Error adding vectors: {e}")
+            return None
+
+    def search_vectors(self, query: str, limit: int = 3):
+        """
+        Searches the collection for vectors similar to the query vector.
+
+        Args:
+            query (str): The query string to be converted into a vector and used for searching.
+            limit (int): The number of search results to return. Defaults to 3.
+
+        Returns:
+            SearchResult or None: Returns the search results if successful, otherwise None.
+        """
+        try:
+            query_vector = self.model.encode(
+                query, normalize_embeddings=True
+            )
+            search_result = self.client.search(
+                collection_name=self.collection_name,
+                query_vector=query_vector,
+                limit=limit,
+            )
+            return search_result
+        except Exception as e:
+            print(f"Error searching vectors: {e}")
+            return None
diff --git a/swarms/memory/schemas.py b/swarms/memory/schemas.py
index bbc71bc2..9147a909 100644
--- a/swarms/memory/schemas.py
+++ b/swarms/memory/schemas.py
@@ -9,7 +9,9 @@ from pydantic import BaseModel, Field
 class TaskInput(BaseModel):
     __root__: Any = Field(
         ...,
-        description="The input parameters for the task. Any value is allowed.",
+        description=(
+            "The input parameters for the task. Any value is allowed."
+        ),
         example='{\n"debug": false,\n"mode": "benchmarks"\n}',
     )
 
@@ -25,7 +27,9 @@ class Artifact(BaseModel):
     )
     relative_path: Optional[str] = Field(
         None,
-        description="Relative path of the artifact in the agent's workspace",
+        description=(
+            "Relative path of the artifact in the agent's workspace"
+        ),
         example="python/code/",
     )
 
@@ -34,7 +38,9 @@ class ArtifactUpload(BaseModel):
     file: bytes = Field(..., description="File to upload")
     relative_path: Optional[str] = Field(
         None,
-        description="Relative path of the artifact in the agent's workspace",
+        description=(
+            "Relative path of the artifact in the agent's workspace"
+        ),
         example="python/code/",
     )
 
@@ -42,7 +48,10 @@ class ArtifactUpload(BaseModel):
 class StepInput(BaseModel):
     __root__: Any = Field(
         ...,
-        description="Input parameters for the task step. Any value is allowed.",
+        description=(
+            "Input parameters for the task step. Any value is"
+            " allowed."
+        ),
         example='{\n"file_to_refactor": "models.py"\n}',
     )
 
@@ -50,7 +59,10 @@ class StepInput(BaseModel):
 class StepOutput(BaseModel):
     __root__: Any = Field(
         ...,
-        description="Output that the task step has produced. Any value is allowed.",
+        description=(
+            "Output that the task step has produced. Any value is"
+            " allowed."
+        ),
         example='{\n"tokens": 7894,\n"estimated_cost": "0,24$"\n}',
     )
 
@@ -59,7 +71,9 @@ class TaskRequestBody(BaseModel):
     input: Optional[str] = Field(
         None,
         description="Input prompt for the task.",
-        example="Write the words you receive to the file 'output.txt'.",
+        example=(
+            "Write the words you receive to the file 'output.txt'."
+        ),
     )
     additional_input: Optional[TaskInput] = None
 
@@ -82,7 +96,9 @@ class Task(TaskRequestBody):
 
 class StepRequestBody(BaseModel):
     input: Optional[str] = Field(
-        None, description="Input prompt for the step.", example="Washington"
+        None,
+        description="Input prompt for the step.",
+        example="Washington",
     )
     additional_input: Optional[StepInput] = None
 
@@ -105,21 +121,28 @@ class Step(StepRequestBody):
         example="6bb1801a-fd80-45e8-899a-4dd723cc602e",
     )
     name: Optional[str] = Field(
-        None, description="The name of the task step.", example="Write to file"
+        None,
+        description="The name of the task step.",
+        example="Write to file",
+    )
+    status: Status = Field(
+        ..., description="The status of the task step."
     )
-    status: Status = Field(..., description="The status of the task step.")
     output: Optional[str] = Field(
         None,
         description="Output of the task step.",
         example=(
-            "I am going to use the write_to_file command and write Washington to a file"
-            " called output.txt <write_to_file('output.txt', 'Washington')"
+            "I am going to use the write_to_file command and write"
+            " Washington to a file called output.txt"
+            " <write_to_file('output.txt', 'Washington')"
         ),
     )
     additional_output: Optional[StepOutput] = None
     artifacts: List[Artifact] = Field(
-        [], description="A list of artifacts that the step has produced."
+        [],
+        description="A list of artifacts that the step has produced.",
     )
     is_last: Optional[bool] = Field(
-        False, description="Whether this is the last step in the task."
+        False,
+        description="Whether this is the last step in the task.",
     )
diff --git a/swarms/memory/utils.py b/swarms/memory/utils.py
index 19cdb989..46c7b020 100644
--- a/swarms/memory/utils.py
+++ b/swarms/memory/utils.py
@@ -31,33 +31,40 @@ def maximal_marginal_relevance(
         return []
     if query_embedding.ndim == 1:
         query_embedding = np.expand_dims(query_embedding, axis=0)
-    similarity_to_query = cosine_similarity(query_embedding, embedding_list)[0]
+    similarity_to_query = cosine_similarity(
+        query_embedding, embedding_list
+    )[0]
     most_similar = int(np.argmax(similarity_to_query))
     idxs = [most_similar]
     selected = np.array([embedding_list[most_similar]])
     while len(idxs) < min(k, len(embedding_list)):
         best_score = -np.inf
         idx_to_add = -1
-        similarity_to_selected = cosine_similarity(embedding_list, selected)
+        similarity_to_selected = cosine_similarity(
+            embedding_list, selected
+        )
         for i, query_score in enumerate(similarity_to_query):
             if i in idxs:
                 continue
             redundant_score = max(similarity_to_selected[i])
             equation_score = (
-                lambda_mult * query_score - (1 - lambda_mult) * redundant_score
+                lambda_mult * query_score
+                - (1 - lambda_mult) * redundant_score
             )
             if equation_score > best_score:
                 best_score = equation_score
                 idx_to_add = i
         idxs.append(idx_to_add)
-        selected = np.append(selected, [embedding_list[idx_to_add]], axis=0)
+        selected = np.append(
+            selected, [embedding_list[idx_to_add]], axis=0
+        )
     return idxs
 
 
 def filter_complex_metadata(
     documents: List[Document],
     *,
-    allowed_types: Tuple[Type, ...] = (str, bool, int, float)
+    allowed_types: Tuple[Type, ...] = (str, bool, int, float),
 ) -> List[Document]:
     """Filter out metadata types that are not supported for a vector store."""
     updated_documents = []
diff --git a/swarms/models/__init__.py b/swarms/models/__init__.py
index f509087c..089585a8 100644
--- a/swarms/models/__init__.py
+++ b/swarms/models/__init__.py
@@ -1,39 +1,49 @@
-import sys
-
-log_file = open("errors.txt", "w")
-sys.stderr = log_file
-
 # LLMs
+from swarms.models.base_llm import AbstractLLM  # noqa: E402
 from swarms.models.anthropic import Anthropic  # noqa: E402
 from swarms.models.petals import Petals  # noqa: E402
 from swarms.models.mistral import Mistral  # noqa: E402
-from swarms.models.openai_models import OpenAI, AzureOpenAI, OpenAIChat  # noqa: E402
-from swarms.models.zephyr import Zephyr  # noqa: E402
+from swarms.models.openai_models import (
+    OpenAI,
+    AzureOpenAI,
+    OpenAIChat,
+)  # noqa: E402
+# from swarms.models.zephyr import Zephyr  # noqa: E402
 from swarms.models.biogpt import BioGPT  # noqa: E402
 from swarms.models.huggingface import HuggingfaceLLM  # noqa: E402
-from swarms.models.wizard_storytelling import WizardLLMStoryTeller  # noqa: E402
+from swarms.models.wizard_storytelling import (
+    WizardLLMStoryTeller,
+)  # noqa: E402
 from swarms.models.mpt import MPT7B  # noqa: E402
 
 # MultiModal Models
+from swarms.models.base_multimodal_model import (
+    BaseMultiModalModel,
+)  # noqa: E402
 from swarms.models.idefics import Idefics  # noqa: E402
-
-# from swarms.models.kosmos_two import Kosmos  # noqa: E402
 from swarms.models.vilt import Vilt  # noqa: E402
 from swarms.models.nougat import Nougat  # noqa: E402
-from swarms.models.layoutlm_document_qa import LayoutLMDocumentQA  # noqa: E402
+from swarms.models.layoutlm_document_qa import (
+    LayoutLMDocumentQA,
+)  # noqa: E402
+from swarms.models.gpt4_vision_api import GPT4VisionAPI  # noqa: E402
 
 # from swarms.models.gpt4v import GPT4Vision
 # from swarms.models.dalle3 import Dalle3
 # from swarms.models.distilled_whisperx import DistilWhisperModel # noqa: E402
+# from swarms.models.whisperx_model import WhisperX  # noqa: E402
+# from swarms.models.kosmos_two import Kosmos  # noqa: E402
 
 __all__ = [
+    "AbstractLLM",
     "Anthropic",
     "Petals",
     "Mistral",
     "OpenAI",
     "AzureOpenAI",
     "OpenAIChat",
-    "Zephyr",
+    # "Zephyr",
+    "BaseMultiModalModel",
     "Idefics",
     # "Kosmos",
     "Vilt",
@@ -45,4 +55,6 @@ __all__ = [
     "WizardLLMStoryTeller",
     # "GPT4Vision",
     # "Dalle3",
+    # "DistilWhisperModel",
+    "GPT4VisionAPI",
 ]
diff --git a/swarms/models/anthropic.py b/swarms/models/anthropic.py
index edaae087..adffe49d 100644
--- a/swarms/models/anthropic.py
+++ b/swarms/models/anthropic.py
@@ -45,12 +45,20 @@ def xor_args(*arg_groups: Tuple[str, ...]) -> Callable:
         def wrapper(*args: Any, **kwargs: Any) -> Any:
             """Validate exactly one arg in each group is not None."""
             counts = [
-                sum(1 for arg in arg_group if kwargs.get(arg) is not None)
+                sum(
+                    1
+                    for arg in arg_group
+                    if kwargs.get(arg) is not None
+                )
                 for arg_group in arg_groups
             ]
-            invalid_groups = [i for i, count in enumerate(counts) if count != 1]
+            invalid_groups = [
+                i for i, count in enumerate(counts) if count != 1
+            ]
             if invalid_groups:
-                invalid_group_names = [", ".join(arg_groups[i]) for i in invalid_groups]
+                invalid_group_names = [
+                    ", ".join(arg_groups[i]) for i in invalid_groups
+                ]
                 raise ValueError(
                     "Exactly one argument in each of the following"
                     " groups must be defined:"
@@ -106,7 +114,10 @@ def mock_now(dt_value):  # type: ignore
 
 
 def guard_import(
-    module_name: str, *, pip_name: Optional[str] = None, package: Optional[str] = None
+    module_name: str,
+    *,
+    pip_name: Optional[str] = None,
+    package: Optional[str] = None,
 ) -> Any:
     """Dynamically imports a module and raises a helpful exception if the module is not
     installed."""
@@ -114,8 +125,9 @@ def guard_import(
         module = importlib.import_module(module_name, package)
     except ImportError:
         raise ImportError(
-            f"Could not import {module_name} python package. "
-            f"Please install it with `pip install {pip_name or module_name}`."
+            f"Could not import {module_name} python package. Please"
+            " install it with `pip install"
+            f" {pip_name or module_name}`."
         )
     return module
 
@@ -129,25 +141,33 @@ def check_package_version(
 ) -> None:
     """Check the version of a package."""
     imported_version = parse(version(package))
-    if lt_version is not None and imported_version >= parse(lt_version):
+    if lt_version is not None and imported_version >= parse(
+        lt_version
+    ):
         raise ValueError(
-            f"Expected {package} version to be < {lt_version}. Received "
-            f"{imported_version}."
+            f"Expected {package} version to be < {lt_version}."
+            f" Received {imported_version}."
         )
-    if lte_version is not None and imported_version > parse(lte_version):
+    if lte_version is not None and imported_version > parse(
+        lte_version
+    ):
         raise ValueError(
-            f"Expected {package} version to be <= {lte_version}. Received "
-            f"{imported_version}."
+            f"Expected {package} version to be <= {lte_version}."
+            f" Received {imported_version}."
         )
-    if gt_version is not None and imported_version <= parse(gt_version):
+    if gt_version is not None and imported_version <= parse(
+        gt_version
+    ):
         raise ValueError(
-            f"Expected {package} version to be > {gt_version}. Received "
-            f"{imported_version}."
+            f"Expected {package} version to be > {gt_version}."
+            f" Received {imported_version}."
         )
-    if gte_version is not None and imported_version < parse(gte_version):
+    if gte_version is not None and imported_version < parse(
+        gte_version
+    ):
         raise ValueError(
-            f"Expected {package} version to be >= {gte_version}. Received "
-            f"{imported_version}."
+            f"Expected {package} version to be >= {gte_version}."
+            f" Received {imported_version}."
         )
 
 
@@ -187,11 +207,14 @@ def build_extra_kwargs(
             )
             extra_kwargs[field_name] = values.pop(field_name)
 
-    invalid_model_kwargs = all_required_field_names.intersection(extra_kwargs.keys())
+    invalid_model_kwargs = all_required_field_names.intersection(
+        extra_kwargs.keys()
+    )
     if invalid_model_kwargs:
         raise ValueError(
-            f"Parameters {invalid_model_kwargs} should be specified explicitly. "
-            "Instead they were passed in as part of `model_kwargs` parameter."
+            f"Parameters {invalid_model_kwargs} should be specified"
+            " explicitly. Instead they were passed in as part of"
+            " `model_kwargs` parameter."
         )
 
     return extra_kwargs
@@ -250,7 +273,9 @@ class _AnthropicCommon(BaseLanguageModel):
     def validate_environment(cls, values: Dict) -> Dict:
         """Validate that api key and python package exists in environment."""
         values["anthropic_api_key"] = convert_to_secret_str(
-            get_from_dict_or_env(values, "anthropic_api_key", "ANTHROPIC_API_KEY")
+            get_from_dict_or_env(
+                values, "anthropic_api_key", "ANTHROPIC_API_KEY"
+            )
         )
         # Get custom api url from environment.
         values["anthropic_api_url"] = get_from_dict_or_env(
@@ -266,12 +291,16 @@ class _AnthropicCommon(BaseLanguageModel):
             check_package_version("anthropic", gte_version="0.3")
             values["client"] = anthropic.Anthropic(
                 base_url=values["anthropic_api_url"],
-                api_key=values["anthropic_api_key"].get_secret_value(),
+                api_key=values[
+                    "anthropic_api_key"
+                ].get_secret_value(),
                 timeout=values["default_request_timeout"],
             )
             values["async_client"] = anthropic.AsyncAnthropic(
                 base_url=values["anthropic_api_url"],
-                api_key=values["anthropic_api_key"].get_secret_value(),
+                api_key=values[
+                    "anthropic_api_key"
+                ].get_secret_value(),
                 timeout=values["default_request_timeout"],
             )
             values["HUMAN_PROMPT"] = anthropic.HUMAN_PROMPT
@@ -305,9 +334,13 @@ class _AnthropicCommon(BaseLanguageModel):
         """Get the identifying parameters."""
         return {**{}, **self._default_params}
 
-    def _get_anthropic_stop(self, stop: Optional[List[str]] = None) -> List[str]:
+    def _get_anthropic_stop(
+        self, stop: Optional[List[str]] = None
+    ) -> List[str]:
         if not self.HUMAN_PROMPT or not self.AI_PROMPT:
-            raise NameError("Please ensure the anthropic package is loaded")
+            raise NameError(
+                "Please ensure the anthropic package is loaded"
+            )
 
         if stop is None:
             stop = []
@@ -354,8 +387,8 @@ class Anthropic(LLM, _AnthropicCommon):
     def raise_warning(cls, values: Dict) -> Dict:
         """Raise warning that this class is deprecated."""
         warnings.warn(
-            "This Anthropic LLM is deprecated. "
-            "Please use `from langchain.chat_models import ChatAnthropic` instead"
+            "This Anthropic LLM is deprecated. Please use `from"
+            " langchain.chat_models import ChatAnthropic` instead"
         )
         return values
 
@@ -366,18 +399,25 @@ class Anthropic(LLM, _AnthropicCommon):
 
     def _wrap_prompt(self, prompt: str) -> str:
         if not self.HUMAN_PROMPT or not self.AI_PROMPT:
-            raise NameError("Please ensure the anthropic package is loaded")
+            raise NameError(
+                "Please ensure the anthropic package is loaded"
+            )
 
         if prompt.startswith(self.HUMAN_PROMPT):
             return prompt  # Already wrapped.
 
         # Guard against common errors in specifying wrong number of newlines.
-        corrected_prompt, n_subs = re.subn(r"^\n*Human:", self.HUMAN_PROMPT, prompt)
+        corrected_prompt, n_subs = re.subn(
+            r"^\n*Human:", self.HUMAN_PROMPT, prompt
+        )
         if n_subs == 1:
             return corrected_prompt
 
         # As a last resort, wrap the prompt ourselves to emulate instruct-style.
-        return f"{self.HUMAN_PROMPT} {prompt}{self.AI_PROMPT} Sure, here you go:\n"
+        return (
+            f"{self.HUMAN_PROMPT} {prompt}{self.AI_PROMPT} Sure, here"
+            " you go:\n"
+        )
 
     def _call(
         self,
@@ -406,7 +446,10 @@ class Anthropic(LLM, _AnthropicCommon):
         if self.streaming:
             completion = ""
             for chunk in self._stream(
-                prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
+                prompt=prompt,
+                stop=stop,
+                run_manager=run_manager,
+                **kwargs,
             ):
                 completion += chunk.text
             return completion
@@ -434,7 +477,10 @@ class Anthropic(LLM, _AnthropicCommon):
         if self.streaming:
             completion = ""
             async for chunk in self._astream(
-                prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
+                prompt=prompt,
+                stop=stop,
+                run_manager=run_manager,
+                **kwargs,
             ):
                 completion += chunk.text
             return completion
@@ -476,7 +522,10 @@ class Anthropic(LLM, _AnthropicCommon):
         params = {**self._default_params, **kwargs}
 
         for token in self.client.completions.create(
-            prompt=self._wrap_prompt(prompt), stop_sequences=stop, stream=True, **params
+            prompt=self._wrap_prompt(prompt),
+            stop_sequences=stop,
+            stream=True,
+            **params,
         ):
             chunk = GenerationChunk(text=token.completion)
             yield chunk
@@ -517,10 +566,14 @@ class Anthropic(LLM, _AnthropicCommon):
             chunk = GenerationChunk(text=token.completion)
             yield chunk
             if run_manager:
-                await run_manager.on_llm_new_token(chunk.text, chunk=chunk)
+                await run_manager.on_llm_new_token(
+                    chunk.text, chunk=chunk
+                )
 
     def get_num_tokens(self, text: str) -> int:
         """Calculate number of tokens."""
         if not self.count_tokens:
-            raise NameError("Please ensure the anthropic package is loaded")
+            raise NameError(
+                "Please ensure the anthropic package is loaded"
+            )
         return self.count_tokens(text)
diff --git a/swarms/models/autotemp.py b/swarms/models/autotemp.py
deleted file mode 100644
index c3abb894..00000000
--- a/swarms/models/autotemp.py
+++ /dev/null
@@ -1,101 +0,0 @@
-import re
-from concurrent.futures import ThreadPoolExecutor, as_completed
-from swarms.models.openai_models import OpenAIChat
-
-
-class AutoTempAgent:
-    """
-    AutoTemp is a tool for automatically selecting the best temperature setting for a given task.
-
-    Flow:
-        1. Generate outputs at a range of temperature settings.
-        2. Evaluate each output using the default temperature setting.
-        3. Select the best output based on the evaluation score.
-        4. Return the best output.
-
-
-    Args:
-        temperature (float, optional): The default temperature setting to use. Defaults to 0.5.
-        api_key (str, optional): Your OpenAI API key. Defaults to None.
-        alt_temps ([type], optional): A list of alternative temperature settings to try. Defaults to None.
-        auto_select (bool, optional): If True, the best temperature setting will be automatically selected. Defaults to True.
-        max_workers (int, optional): The maximum number of workers to use when generating outputs. Defaults to 6.
-
-    Returns:
-        [type]: [description]
-
-    Examples:
-        >>> from swarms.demos.autotemp import AutoTemp
-        >>> autotemp = AutoTemp()
-        >>> autotemp.run("Generate a 10,000 word blog on mental clarity and the benefits of meditation.", "0.4,0.6,0.8,1.0,1.2,1.4")
-        Best AutoTemp Output (Temp 0.4 | Score: 100.0):
-        Generate a 10,000 word blog on mental clarity and the benefits of meditation.
-
-    """
-
-    def __init__(
-        self,
-        temperature: float = 0.5,
-        api_key: str = None,
-        alt_temps=None,
-        auto_select=True,
-        max_workers=6,
-    ):
-        self.alt_temps = alt_temps if alt_temps else [0.4, 0.6, 0.8, 1.0, 1.2, 1.4]
-        self.auto_select = auto_select
-        self.max_workers = max_workers
-        self.temperature = temperature
-        self.alt_temps = alt_temps
-        self.llm = OpenAIChat(
-            openai_api_key=api_key,
-            temperature=temperature,
-        )
-
-    def evaluate_output(self, output: str):
-        """Evaluate the output using the default temperature setting."""
-        eval_prompt = f"""
-            Evaluate the following output which was generated at a temperature setting of {self.temperature}. 
-            Provide a precise score from 0.0 to 100.0, considering the criteria of relevance, clarity, utility, pride, and delight.
-
-            Output to evaluate:
-            ---
-            {output}
-            ---
-            """
-        score_text = self.llm(prompt=eval_prompt)
-        score_match = re.search(r"\b\d+(\.\d)?\b", score_text)
-        return round(float(score_match.group()), 1) if score_match else 0.0
-
-    def run(self, task: str, temperature_string):
-        """Run the AutoTemp agent."""
-        temperature_list = [
-            float(temp.strip()) for temp in temperature_string.split(",")
-        ]
-        outputs = {}
-        scores = {}
-        with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
-            future_to_temp = {
-                executor.submit(self.llm.generate, task, temp): temp
-                for temp in temperature_list
-            }
-            for future in as_completed(future_to_temp):
-                temp = future_to_temp[future]
-                output_text = future.result()
-                outputs[temp] = output_text
-                scores[temp] = self.evaluate_output(output_text, temp)
-
-        if not scores:
-            return "No valid outputs generated.", None
-
-        sorted_scores = sorted(scores.items(), key=lambda item: item[1], reverse=True)
-        best_temp, best_score = sorted_scores[0]
-        best_output = outputs[best_temp]
-
-        return (
-            f"Best AutoTemp Output (Temp {best_temp} | Score: {best_score}):\n{best_output}"
-            if self.auto_select
-            else "\n".join(
-                f"Temp {temp} | Score: {score}:\n{outputs[temp]}"
-                for temp, score in sorted_scores
-            )
-        )
diff --git a/swarms/models/base.py b/swarms/models/base.py
deleted file mode 100644
index 4e92ae45..00000000
--- a/swarms/models/base.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import time
-from abc import ABC, abstractmethod
-
-
-def count_tokens(text: str) -> int:
-    return len(text.split())
-
-
-class AbstractModel(ABC):
-    """
-    AbstractModel
-
-    """
-
-    # abstract base class for language models
-    def __init__(self):
-        self.start_time = None
-        self.end_time = None
-        self.temperature = 1.0
-        self.max_tokens = None
-        self.history = ""
-
-    @abstractmethod
-    def run(self, task: str) -> str:
-        """generate text using language model"""
-        pass
-
-    def chat(self, task: str, history: str = "") -> str:
-        """Chat with the model"""
-        complete_task = task + " | " + history  # Delimiter for clarity
-        return self.run(complete_task)
-
-    def __call__(self, task: str) -> str:
-        """Call the model"""
-        return self.run(task)
-
-    def _sec_to_first_token(self) -> float:
-        # Assuming the first token appears instantly after the model starts
-        return 0.001
-
-    def _tokens_per_second(self) -> float:
-        """Tokens per second"""
-        elapsed_time = self.end_time - self.start_time
-        if elapsed_time == 0:
-            return float("inf")
-        return self._num_tokens() / elapsed_time
-
-    def _num_tokens(self, text: str) -> int:
-        """Number of tokens"""
-        return count_tokens(text)
-
-    def _time_for_generation(self, task: str) -> float:
-        """Time for Generation"""
-        self.start_time = time.time()
-        self.run(task)
-        self.end_time = time.time()
-        return self.end_time - self.start_time
-
-    @abstractmethod
-    def generate_summary(self, text: str) -> str:
-        """Generate Summary"""
-        pass
-
-    def set_temperature(self, value: float):
-        """Set Temperature"""
-        self.temperature = value
-
-    def set_max_tokens(self, value: int):
-        """Set new max tokens"""
-        self.max_tokens = value
-
-    def clear_history(self):
-        """Clear history"""
-        self.history = ""
-
-    def get_generation_time(self) -> float:
-        """Get generation time"""
-        if self.start_time and self.end_time:
-            return self.end_time - self.start_time
-        return 0
-
-    def metrics(self) -> str:
-        _sec_to_first_token = self._sec_to_first_token()
-        _tokens_per_second = self._tokens_per_second()
-        _num_tokens = self._num_tokens(self.history)
-        _time_for_generation = self._time_for_generation(self.history)
-
-        return f"""
-        SEC TO FIRST TOKEN: {_sec_to_first_token}
-        TOKENS/SEC: {_tokens_per_second}
-        TOKENS: {_num_tokens}
-        Tokens/SEC: {_time_for_generation}
-        """
diff --git a/swarms/models/base_llm.py b/swarms/models/base_llm.py
new file mode 100644
index 00000000..8720cba9
--- /dev/null
+++ b/swarms/models/base_llm.py
@@ -0,0 +1,384 @@
+import os
+import logging
+import time
+from abc import ABC, abstractmethod
+from typing import Optional, List
+import asyncio
+
+
+def count_tokens(text: str) -> int:
+    """Count tokens
+
+    Args:
+        text (str): _description_
+
+    Returns:
+        int: _description_
+    """
+    return len(text.split())
+
+
+class AbstractLLM(ABC):
+    """Abstract Language Model that defines the interface for all language models
+
+    Args:
+        model_name (Optional[str], optional): _description_. Defaults to None.
+        max_tokens (Optional[int], optional): _description_. Defaults to None.
+        max_length (Optional[int], optional): _description_. Defaults to None.
+        temperature (Optional[float], optional): _description_. Defaults to None.
+        top_k (Optional[float], optional): _description_. Defaults to None.
+        top_p (Optional[float], optional): _description_. Defaults to None.
+        system_prompt (Optional[str], optional): _description_. Defaults to None.
+        beam_width (Optional[int], optional): _description_. Defaults to None.
+        num_return_sequences (Optional[int], optional): _description_. Defaults to None.
+        seed (Optional[int], optional): _description_. Defaults to None.
+        frequency_penalty (Optional[float], optional): _description_. Defaults to None.
+        presence_penalty (Optional[float], optional): _description_. Defaults to None.
+        stop_token (Optional[str], optional): _description_. Defaults to None.
+        length_penalty (Optional[float], optional): _description_. Defaults to None.
+        role (Optional[str], optional): _description_. Defaults to None.
+        do_sample (Optional[bool], optional): _description_. Defaults to None.
+        early_stopping (Optional[bool], optional): _description_. Defaults to None.
+        num_beams (Optional[int], optional): _description_. Defaults to None.
+        repition_penalty (Optional[float], optional): _description_. Defaults to None.
+        pad_token_id (Optional[int], optional): _description_. Defaults to None.
+        eos_token_id (Optional[int], optional): _description_. Defaults to None.
+        bos_token_id (Optional[int], optional): _description_. Defaults to None.
+        device (Optional[str], optional): _description_. Defaults to None.
+        *args: _description_
+        **kwargs: _description_
+
+
+    """
+
+    def __init__(
+        self,
+        model_name: Optional[str] = None,
+        max_tokens: Optional[int] = None,
+        max_length: Optional[int] = None,
+        temperature: Optional[float] = None,
+        top_k: Optional[float] = None,
+        top_p: Optional[float] = None,
+        system_prompt: Optional[str] = None,
+        beam_width: Optional[int] = None,
+        num_return_sequences: Optional[int] = None,
+        seed: Optional[int] = None,
+        frequency_penalty: Optional[float] = None,
+        presence_penalty: Optional[float] = None,
+        stop_token: Optional[str] = None,
+        length_penalty: Optional[float] = None,
+        role: Optional[str] = None,
+        do_sample: Optional[bool] = None,
+        early_stopping: Optional[bool] = None,
+        num_beams: Optional[int] = None,
+        repition_penalty: Optional[float] = None,
+        pad_token_id: Optional[int] = None,
+        eos_token_id: Optional[int] = None,
+        bos_token_id: Optional[int] = None,
+        device: Optional[str] = None,
+        *args,
+        **kwargs,
+    ):
+        self.model_name = model_name
+        self.max_tokens = max_tokens
+        self.temperature = temperature
+        self.top_k = top_k
+        self.top_p = top_p
+        self.system_prompt = system_prompt
+        self.beam_width = beam_width
+        self.num_return_sequences = num_return_sequences
+        self.seed = seed
+        self.frequency_penalty = frequency_penalty
+        self.presence_penalty = presence_penalty
+        self.stop_token = stop_token
+        self.length_penalty = length_penalty
+        self.role = role
+        self.max_length = max_length
+        self.do_sample = do_sample
+        self.early_stopping = early_stopping
+        self.num_beams = num_beams
+        self.repition_penalty = repition_penalty
+        self.pad_token_id = pad_token_id
+        self.eos_token_id = eos_token_id
+        self.bos_token_id = bos_token_id
+        self.device = device
+
+        # Attributes
+        self.history = ""
+        self.start_time = None
+        self.end_time = None
+        self.history = []
+        self.memory = {
+            "input": [],
+            "output": [],
+            "task": [],
+            "time": [],
+            "role": [],
+            "model": [],
+        }
+
+    @abstractmethod
+    def run(self, task: Optional[str] = None, *args, **kwargs) -> str:
+        """generate text using language model"""
+        pass
+
+    async def arun(self, task: Optional[str] = None, *args, **kwargs):
+        """Asynchronous run
+
+        Args:
+            task (Optional[str], optional): _description_. Defaults to None.
+        """
+        loop = asyncio.get_event_loop()
+        result = await loop.run_in_executor(None, self.run, task)
+        return result
+
+    def batch_run(self, tasks: List[str], *args, **kwargs):
+        """Batch run with language model
+
+        Args:
+            tasks (List[str]): _description_
+
+        Returns:
+            _type_: _description_
+        """
+        return [self.run(task) for task in tasks]
+
+    async def abatch_run(self, tasks: List[str], *args, **kwargs):
+        """Asynchronous batch run with language model
+
+        Args:
+            tasks (List[str]): _description_
+
+        Returns:
+            _type_: _description_
+        """
+        return await asyncio.gather(
+            *(self.arun(task) for task in tasks)
+        )
+
+    def chat(self, task: str, history: str = "") -> str:
+        """Chat with the model"""
+        complete_task = (
+            task + " | " + history
+        )  # Delimiter for clarity
+        return self.run(complete_task)
+
+    def __call__(self, task: str) -> str:
+        """Call the model"""
+        return self.run(task)
+
+    def _tokens_per_second(self) -> float:
+        """Tokens per second"""
+        elapsed_time = self.end_time - self.start_time
+        if elapsed_time == 0:
+            return float("inf")
+        return self._num_tokens() / elapsed_time
+
+    def _num_tokens(self, text: str) -> int:
+        """Number of tokens"""
+        return count_tokens(text)
+
+    def _time_for_generation(self, task: str) -> float:
+        """Time for Generation"""
+        self.start_time = time.time()
+        self.run(task)
+        self.end_time = time.time()
+        return self.end_time - self.start_time
+
+    @abstractmethod
+    def generate_summary(self, text: str) -> str:
+        """Generate Summary"""
+        pass
+
+    def set_temperature(self, value: float):
+        """Set Temperature"""
+        self.temperature = value
+
+    def set_max_tokens(self, value: int):
+        """Set new max tokens"""
+        self.max_tokens = value
+
+    def clear_history(self):
+        """Clear history"""
+        self.history = []
+
+    def enable_logging(self, log_file: str = "model.log"):
+        """Initialize logging for the model."""
+        logging.basicConfig(filename=log_file, level=logging.INFO)
+        self.log_file = log_file
+
+    def log_event(self, message: str):
+        """Log an event."""
+        logging.info(
+            f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}"
+        )
+
+    def save_checkpoint(self, checkpoint_dir: str = "checkpoints"):
+        """Save the model state."""
+        # This is a placeholder for actual checkpointing logic.
+        if not os.path.exists(checkpoint_dir):
+            os.makedirs(checkpoint_dir)
+        checkpoint_path = os.path.join(
+            checkpoint_dir,
+            f'checkpoint_{time.strftime("%Y%m%d-%H%M%S")}.ckpt',
+        )
+        # Save model state to checkpoint_path
+        self.log_event(f"Model checkpoint saved at {checkpoint_path}")
+
+    def load_checkpoint(self, checkpoint_path: str):
+        """Load the model state from a checkpoint."""
+        # This is a placeholder for actual loading logic.
+        # Load model state from checkpoint_path
+        self.log_event(f"Model state loaded from {checkpoint_path}")
+
+    def toggle_creative_mode(self, enable: bool):
+        """Toggle creative mode for the model."""
+        self.creative_mode = enable
+        self.log_event(
+            f"Creative mode {'enabled' if enable else 'disabled'}."
+        )
+
+    def track_resource_utilization(self):
+        """Track and report resource utilization."""
+        # This is a placeholder for actual tracking logic.
+        # Logic to track CPU, memory, etc.
+        utilization_report = "Resource utilization report here"
+        return utilization_report
+
+    def get_generation_time(self) -> float:
+        """Get generation time"""
+        if self.start_time and self.end_time:
+            return self.end_time - self.start_time
+        return 0
+
+    def set_max_length(self, max_length: int):
+        """Set max length
+
+        Args:
+            max_length (int): _description_
+        """
+        self.max_length = max_length
+
+    def set_model_name(self, model_name: str):
+        """Set model name
+
+        Args:
+            model_name (str): _description_
+        """
+        self.model_name = model_name
+
+    def set_frequency_penalty(self, frequency_penalty: float):
+        """Set frequency penalty
+
+        Args:
+            frequency_penalty (float): _description_
+        """
+        self.frequency_penalty = frequency_penalty
+
+    def set_presence_penalty(self, presence_penalty: float):
+        """Set presence penalty
+
+        Args:
+            presence_penalty (float): _description_
+        """
+        self.presence_penalty = presence_penalty
+
+    def set_stop_token(self, stop_token: str):
+        """Set stop token
+
+        Args:
+            stop_token (str): _description_
+        """
+        self.stop_token = stop_token
+
+    def set_length_penalty(self, length_penalty: float):
+        """Set length penalty
+
+        Args:
+            length_penalty (float): _description_
+        """
+        self.length_penalty = length_penalty
+
+    def set_role(self, role: str):
+        """Set role
+
+        Args:
+            role (str): _description_
+        """
+        self.role = role
+
+    def set_top_k(self, top_k: int):
+        """Set top k
+
+        Args:
+            top_k (int): _description_
+        """
+        self.top_k = top_k
+
+    def set_top_p(self, top_p: float):
+        """Set top p
+
+        Args:
+            top_p (float): _description_
+        """
+        self.top_p = top_p
+
+    def set_num_beams(self, num_beams: int):
+        """Set num beams
+
+        Args:
+            num_beams (int): _description_
+        """
+        self.num_beams = num_beams
+
+    def set_do_sample(self, do_sample: bool):
+        """set do sample
+
+
+        Args:
+            do_sample (bool): _description_
+        """
+        self.do_sample = do_sample
+
+    def set_early_stopping(self, early_stopping: bool):
+        """set early stopping
+
+        Args:
+            early_stopping (bool): _description_
+        """
+        self.early_stopping = early_stopping
+
+    def set_seed(self, seed: int):
+        """Set seed
+
+        Args:
+            seed ([type]): [description]
+        """
+        self.seed = seed
+
+    def set_device(self, device: str):
+        """Set device
+
+        Args:
+            device (str): _description_
+        """
+        self.device = device
+
+    def metrics(self) -> str:
+        """
+        Metrics
+
+        Returns:
+            str: _description_
+        """
+        _sec_to_first_token = self._sec_to_first_token()
+        _tokens_per_second = self._tokens_per_second()
+        _num_tokens = self._num_tokens(self.history)
+        _time_for_generation = self._time_for_generation(self.history)
+
+        return f"""
+        SEC TO FIRST TOKEN: {_sec_to_first_token}
+        TOKENS/SEC: {_tokens_per_second}
+        TOKENS: {_num_tokens}
+        Tokens/SEC: {_time_for_generation}
+        """
diff --git a/swarms/models/base_multimodal_model.py b/swarms/models/base_multimodal_model.py
new file mode 100644
index 00000000..30e45149
--- /dev/null
+++ b/swarms/models/base_multimodal_model.py
@@ -0,0 +1,295 @@
+import asyncio
+import base64
+import concurrent.futures
+import time
+from abc import abstractmethod
+from concurrent.futures import ThreadPoolExecutor
+from io import BytesIO
+from typing import List, Optional, Tuple
+
+import requests
+from PIL import Image
+from termcolor import colored
+
+
+class BaseMultiModalModel:
+    """
+    Base class for multimodal models
+
+
+    Args:
+        model_name (Optional[str], optional): Model name. Defaults to None.
+        temperature (Optional[int], optional): Temperature. Defaults to 0.5.
+        max_tokens (Optional[int], optional): Max tokens. Defaults to 500.
+        max_workers (Optional[int], optional): Max workers. Defaults to 10.
+        top_p (Optional[int], optional): Top p. Defaults to 1.
+        top_k (Optional[int], optional): Top k. Defaults to 50.
+        beautify (Optional[bool], optional): Beautify. Defaults to False.
+        device (Optional[str], optional): Device. Defaults to "cuda".
+        max_new_tokens (Optional[int], optional): Max new tokens. Defaults to 500.
+        retries (Optional[int], optional): Retries. Defaults to 3.
+
+    Examples:
+        >>> from swarms.models.base_multimodal_model import BaseMultiModalModel
+        >>> model = BaseMultiModalModel()
+        >>> model.run("Generate a summary of this text")
+        >>> model.run("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")
+        >>> model.run_batch(["Generate a summary of this text", "Generate a summary of this text"])
+        >>> model.run_batch([("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"), ("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")])
+        >>> model.run_batch_async(["Generate a summary of this text", "Generate a summary of this text"])
+        >>> model.run_batch_async([("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"), ("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")])
+        >>> model.run_batch_async_with_retries(["Generate a summary of this text", "Generate a summary of this text"])
+        >>> model.run_batch_async_with_retries([("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"), ("Generate a summary of this text", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")])
+        >>> model.generate_summary("Generate a summary of this text")
+        >>> model.set_temperature(0.5)
+        >>> model.set_max_tokens(500)
+        >>> model.get_generation_time()
+        >>> model.get_chat_history()
+        >>> model.get_unique_chat_history()
+        >>> model.get_chat_history_length()
+        >>> model.get_unique_chat_history_length()
+        >>> model.get_chat_history_tokens()
+        >>> model.print_beautiful("Print this beautifully")
+        >>> model.stream("Stream this")
+        >>> model.unique_chat_history()
+        >>> model.clear_chat_history()
+        >>> model.get_img_from_web("https://www.google.com/images/branding/googlelogo/")
+
+    """
+
+    def __init__(
+        self,
+        model_name: Optional[str],
+        temperature: Optional[int] = 0.5,
+        max_tokens: Optional[int] = 500,
+        max_workers: Optional[int] = 10,
+        top_p: Optional[int] = 1,
+        top_k: Optional[int] = 50,
+        beautify: Optional[bool] = False,
+        device: Optional[str] = "cuda",
+        max_new_tokens: Optional[int] = 500,
+        retries: Optional[int] = 3,
+        system_prompt: Optional[str] = None,
+        meta_prompt: Optional[str] = None,
+        *args,
+        **kwargs,
+    ):
+        self.model_name = model_name
+        self.temperature = temperature
+        self.max_tokens = max_tokens
+        self.max_workers = max_workers
+        self.top_p = top_p
+        self.top_k = top_k
+        self.beautify = beautify
+        self.device = device
+        self.max_new_tokens = max_new_tokens
+        self.retries = retries
+        self.chat_history = []
+
+    @abstractmethod
+    def __call__(self, text: str, img: str):
+        """Run the model"""
+        pass
+
+    def run(self, task: str, img: str):
+        """Run the model"""
+        pass
+
+    async def arun(self, task: str, img: str):
+        """Run the model asynchronously"""
+        pass
+
+    def get_img_from_web(self, img: str):
+        """Get the image from the web"""
+        try:
+            response = requests.get(img)
+            response.raise_for_status()
+            image_pil = Image.open(BytesIO(response.content))
+            return image_pil
+        except requests.RequestException as error:
+            print(
+                f"Error fetching image from {img} and error: {error}"
+            )
+            return None
+
+    def encode_img(self, img: str):
+        """Encode the image to base64"""
+        with open(img, "rb") as image_file:
+            return base64.b64encode(image_file.read()).decode("utf-8")
+
+    def get_img(self, img: str):
+        """Get the image from the path"""
+        image_pil = Image.open(img)
+        return image_pil
+
+    def clear_chat_history(self):
+        """Clear the chat history"""
+        self.chat_history = []
+
+    def run_many(
+        self,
+        tasks: List[str],
+        imgs: List[str],
+    ):
+        """
+        Run the model on multiple tasks and images all at once using concurrent
+
+        Args:
+            tasks (List[str]): List of tasks
+            imgs (List[str]): List of image paths
+
+        Returns:
+            List[str]: List of responses
+
+
+        """
+        # Instantiate the thread pool executor
+        with ThreadPoolExecutor(
+            max_workers=self.max_workers
+        ) as executor:
+            results = executor.map(self.run, tasks, imgs)
+
+        # Print the results for debugging
+        for result in results:
+            print(result)
+
+    def run_batch(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
+        """Process a batch of tasks and images"""
+        with concurrent.futures.ThreadPoolExecutor() as executor:
+            futures = [
+                executor.submit(self.run, task, img)
+                for task, img in tasks_images
+            ]
+            results = [future.result() for future in futures]
+        return results
+
+    async def run_batch_async(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
+        """Process a batch of tasks and images asynchronously"""
+        loop = asyncio.get_event_loop()
+        futures = [
+            loop.run_in_executor(None, self.run, task, img)
+            for task, img in tasks_images
+        ]
+        return await asyncio.gather(*futures)
+
+    async def run_batch_async_with_retries(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
+        """Process a batch of tasks and images asynchronously with retries"""
+        loop = asyncio.get_event_loop()
+        futures = [
+            loop.run_in_executor(
+                None, self.run_with_retries, task, img
+            )
+            for task, img in tasks_images
+        ]
+        return await asyncio.gather(*futures)
+
+    def unique_chat_history(self):
+        """Get the unique chat history"""
+        return list(set(self.chat_history))
+
+    def run_with_retries(self, task: str, img: str):
+        """Run the model with retries"""
+        for i in range(self.retries):
+            try:
+                return self.run(task, img)
+            except Exception as error:
+                print(f"Error with the request {error}")
+                continue
+
+    def run_batch_with_retries(
+        self, tasks_images: List[Tuple[str, str]]
+    ):
+        """Run the model with retries"""
+        for i in range(self.retries):
+            try:
+                return self.run_batch(tasks_images)
+            except Exception as error:
+                print(f"Error with the request {error}")
+                continue
+
+    def _tokens_per_second(self) -> float:
+        """Tokens per second"""
+        elapsed_time = self.end_time - self.start_time
+        if elapsed_time == 0:
+            return float("inf")
+        return self._num_tokens() / elapsed_time
+
+    def _time_for_generation(self, task: str) -> float:
+        """Time for Generation"""
+        self.start_time = time.time()
+        self.run(task)
+        self.end_time = time.time()
+        return self.end_time - self.start_time
+
+    @abstractmethod
+    def generate_summary(self, text: str) -> str:
+        """Generate Summary"""
+        pass
+
+    def set_temperature(self, value: float):
+        """Set Temperature"""
+        self.temperature = value
+
+    def set_max_tokens(self, value: int):
+        """Set new max tokens"""
+        self.max_tokens = value
+
+    def get_generation_time(self) -> float:
+        """Get generation time"""
+        if self.start_time and self.end_time:
+            return self.end_time - self.start_time
+        return 0
+
+    def get_chat_history(self):
+        """Get the chat history"""
+        return self.chat_history
+
+    def get_unique_chat_history(self):
+        """Get the unique chat history"""
+        return list(set(self.chat_history))
+
+    def get_chat_history_length(self):
+        """Get the chat history length"""
+        return len(self.chat_history)
+
+    def get_unique_chat_history_length(self):
+        """Get the unique chat history length"""
+        return len(list(set(self.chat_history)))
+
+    def get_chat_history_tokens(self):
+        """Get the chat history tokens"""
+        return self._num_tokens()
+
+    def print_beautiful(self, content: str, color: str = "cyan"):
+        """Print Beautifully with termcolor"""
+        content = colored(content, color)
+        print(content)
+
+    def stream(self, content: str):
+        """Stream the output
+
+        Args:
+            content (str): _description_
+        """
+        for chunk in content:
+            print(chunk)
+
+    def meta_prompt(self):
+        """Meta Prompt
+
+        Returns:
+            _type_: _description_
+        """
+        META_PROMPT = """
+        For any labels or markings on an image that you reference in your response, please 
+        enclose them in square brackets ([]) and list them explicitly. Do not use ranges; for 
+        example, instead of '1 - 4', list as '[1], [2], [3], [4]'. These labels could be 
+        numbers or letters and typically correspond to specific segments or parts of the image.
+        """
+        return META_PROMPT
diff --git a/swarms/models/bioclip.py b/swarms/models/bioclip.py
index c2b4bfa5..e2d070af 100644
--- a/swarms/models/bioclip.py
+++ b/swarms/models/bioclip.py
@@ -98,7 +98,9 @@ class BioClip:
         ) = open_clip.create_model_and_transforms(model_path)
         self.tokenizer = open_clip.get_tokenizer(model_path)
         self.device = (
-            torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
+            torch.device("cuda")
+            if torch.cuda.is_available()
+            else torch.device("cpu")
         )
         self.model.to(self.device)
         self.model.eval()
@@ -110,19 +112,26 @@ class BioClip:
         template: str = "this is a photo of ",
         context_length: int = 256,
     ):
-        image = torch.stack([self.preprocess_val(Image.open(img_path))]).to(self.device)
+        image = torch.stack(
+            [self.preprocess_val(Image.open(img_path))]
+        ).to(self.device)
         texts = self.tokenizer(
-            [template + l for l in labels], context_length=context_length
+            [template + l for l in labels],
+            context_length=context_length,
         ).to(self.device)
 
         with torch.no_grad():
-            image_features, text_features, logit_scale = self.model(image, texts)
+            image_features, text_features, logit_scale = self.model(
+                image, texts
+            )
             logits = (
                 (logit_scale * image_features @ text_features.t())
                 .detach()
                 .softmax(dim=-1)
             )
-            sorted_indices = torch.argsort(logits, dim=-1, descending=True)
+            sorted_indices = torch.argsort(
+                logits, dim=-1, descending=True
+            )
             logits = logits.cpu().numpy()
             sorted_indices = sorted_indices.cpu().numpy()
 
@@ -142,7 +151,12 @@ class BioClip:
         title = (
             metadata["filename"]
             + "\n"
-            + "\n".join([f"{k}: {v*100:.1f}" for k, v in metadata["top_probs"].items()])
+            + "\n".join(
+                [
+                    f"{k}: {v*100:.1f}"
+                    for k, v in metadata["top_probs"].items()
+                ]
+            )
         )
         ax.set_title(title, fontsize=14)
         plt.tight_layout()
diff --git a/swarms/models/biogpt.py b/swarms/models/biogpt.py
index 83c31e55..9ee5b513 100644
--- a/swarms/models/biogpt.py
+++ b/swarms/models/biogpt.py
@@ -34,7 +34,12 @@ advantage of BioGPT on biomedical literature to generate fluent descriptions for
 """
 
 import torch
-from transformers import pipeline, set_seed, BioGptTokenizer, BioGptForCausalLM
+from transformers import (
+    pipeline,
+    set_seed,
+    BioGptTokenizer,
+    BioGptForCausalLM,
+)
 
 
 class BioGPT:
@@ -85,8 +90,12 @@ class BioGPT:
         self.do_sample = do_sample
         self.min_length = min_length
 
-        self.model = BioGptForCausalLM.from_pretrained(self.model_name)
-        self.tokenizer = BioGptTokenizer.from_pretrained(self.model_name)
+        self.model = BioGptForCausalLM.from_pretrained(
+            self.model_name
+        )
+        self.tokenizer = BioGptTokenizer.from_pretrained(
+            self.model_name
+        )
 
     def __call__(self, text: str):
         """
@@ -103,7 +112,9 @@ class BioGPT:
         """
         set_seed(42)
         generator = pipeline(
-            "text-generation", model=self.model, tokenizer=self.tokenizer
+            "text-generation",
+            model=self.model,
+            tokenizer=self.tokenizer,
         )
         out = generator(
             text,
@@ -154,9 +165,11 @@ class BioGPT:
                 min_length=self.min_length,
                 max_length=self.max_length,
                 num_beams=num_beams,
-                early_stopping=early_stopping
+                early_stopping=early_stopping,
             )
-        return self.tokenizer.decode(beam_output[0], skip_special_tokens=True)
+        return self.tokenizer.decode(
+            beam_output[0], skip_special_tokens=True
+        )
 
     # Feature 1: Set a new tokenizer and model
     def set_pretrained_model(self, model_name):
@@ -167,8 +180,12 @@ class BioGPT:
             model_name (str): Name of the pretrained model.
         """
         self.model_name = model_name
-        self.model = BioGptForCausalLM.from_pretrained(self.model_name)
-        self.tokenizer = BioGptTokenizer.from_pretrained(self.model_name)
+        self.model = BioGptForCausalLM.from_pretrained(
+            self.model_name
+        )
+        self.tokenizer = BioGptTokenizer.from_pretrained(
+            self.model_name
+        )
 
     # Feature 2: Get the model's config details
     def get_config(self):
diff --git a/swarms/models/cohere_chat.py b/swarms/models/cohere_chat.py
index c583b827..1a31d82e 100644
--- a/swarms/models/cohere_chat.py
+++ b/swarms/models/cohere_chat.py
@@ -32,7 +32,9 @@ def _create_retry_decorator(llm) -> Callable[[Any], Any]:
     return retry(
         reraise=True,
         stop=stop_after_attempt(llm.max_retries),
-        wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
+        wait=wait_exponential(
+            multiplier=1, min=min_seconds, max=max_seconds
+        ),
         retry=(retry_if_exception_type(cohere.error.CohereError)),
         before_sleep=before_sleep_log(logger, logging.WARNING),
     )
@@ -65,7 +67,9 @@ class BaseCohere(Serializable):
 
     client: Any  #: :meta private:
     async_client: Any  #: :meta private:
-    model: Optional[str] = Field(default=None, description="Model name to use.")
+    model: Optional[str] = Field(
+        default=None, description="Model name to use."
+    )
     """Model name to use."""
 
     temperature: float = 0.75
@@ -96,7 +100,9 @@ class BaseCohere(Serializable):
                 values, "cohere_api_key", "COHERE_API_KEY"
             )
             client_name = values["user_agent"]
-            values["client"] = cohere.Client(cohere_api_key, client_name=client_name)
+            values["client"] = cohere.Client(
+                cohere_api_key, client_name=client_name
+            )
             values["async_client"] = cohere.AsyncClient(
                 cohere_api_key, client_name=client_name
             )
@@ -172,17 +178,23 @@ class Cohere(LLM, BaseCohere):
         """Return type of llm."""
         return "cohere"
 
-    def _invocation_params(self, stop: Optional[List[str]], **kwargs: Any) -> dict:
+    def _invocation_params(
+        self, stop: Optional[List[str]], **kwargs: Any
+    ) -> dict:
         params = self._default_params
         if self.stop is not None and stop is not None:
-            raise ValueError("`stop` found in both the input and default params.")
+            raise ValueError(
+                "`stop` found in both the input and default params."
+            )
         elif self.stop is not None:
             params["stop_sequences"] = self.stop
         else:
             params["stop_sequences"] = stop
         return {**params, **kwargs}
 
-    def _process_response(self, response: Any, stop: Optional[List[str]]) -> str:
+    def _process_response(
+        self, response: Any, stop: Optional[List[str]]
+    ) -> str:
         text = response.generations[0].text
         # If stop tokens are provided, Cohere's endpoint returns them.
         # In order to make this consistent with other endpoints, we strip them.
diff --git a/swarms/models/dalle3.py b/swarms/models/dalle3.py
index 7d9bcf5d..40f63418 100644
--- a/swarms/models/dalle3.py
+++ b/swarms/models/dalle3.py
@@ -116,7 +116,9 @@ class Dalle3:
         byte_array = byte_stream.getvalue()
         return byte_array
 
-    @backoff.on_exception(backoff.expo, Exception, max_time=max_time_seconds)
+    @backoff.on_exception(
+        backoff.expo, Exception, max_time=max_time_seconds
+    )
     def __call__(self, task: str):
         """
         Text to image conversion using the Dalle3 API
@@ -169,8 +171,8 @@ class Dalle3:
             print(
                 colored(
                     (
-                        f"Error running Dalle3: {error} try optimizing your api key and"
-                        " or try again"
+                        f"Error running Dalle3: {error} try"
+                        " optimizing your api key and or try again"
                     ),
                     "red",
                 )
@@ -198,7 +200,9 @@ class Dalle3:
             with open(full_path, "wb") as file:
                 file.write(response.content)
         else:
-            raise ValueError(f"Failed to download image from {img_url}")
+            raise ValueError(
+                f"Failed to download image from {img_url}"
+            )
 
     def create_variations(self, img: str):
         """
@@ -234,22 +238,28 @@ class Dalle3:
             print(
                 colored(
                     (
-                        f"Error running Dalle3: {error} try optimizing your api key and"
-                        " or try again"
+                        f"Error running Dalle3: {error} try"
+                        " optimizing your api key and or try again"
                     ),
                     "red",
                 )
             )
-            print(colored(f"Error running Dalle3: {error.http_status}", "red"))
-            print(colored(f"Error running Dalle3: {error.error}", "red"))
+            print(
+                colored(
+                    f"Error running Dalle3: {error.http_status}",
+                    "red",
+                )
+            )
+            print(
+                colored(f"Error running Dalle3: {error.error}", "red")
+            )
             raise error
 
     def print_dashboard(self):
         """Print the Dalle3 dashboard"""
         print(
             colored(
-                (
-                    f"""Dalle3 Dashboard: 
+                f"""Dalle3 Dashboard: 
                     --------------------
 
                     Model: {self.model}
@@ -265,13 +275,14 @@ class Dalle3:
                     --------------------
                     
                     
-                    """
-                ),
+                    """,
                 "green",
             )
         )
 
-    def process_batch_concurrently(self, tasks: List[str], max_workers: int = 5):
+    def process_batch_concurrently(
+        self, tasks: List[str], max_workers: int = 5
+    ):
         """
 
         Process a batch of tasks concurrently
@@ -293,10 +304,16 @@ class Dalle3:
         ['https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png',
 
         """
-        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
-            future_to_task = {executor.submit(self, task): task for task in tasks}
+        with concurrent.futures.ThreadPoolExecutor(
+            max_workers=max_workers
+        ) as executor:
+            future_to_task = {
+                executor.submit(self, task): task for task in tasks
+            }
             results = []
-            for future in concurrent.futures.as_completed(future_to_task):
+            for future in concurrent.futures.as_completed(
+                future_to_task
+            ):
                 task = future_to_task[future]
                 try:
                     img = future.result()
@@ -307,14 +324,28 @@ class Dalle3:
                     print(
                         colored(
                             (
-                                f"Error running Dalle3: {error} try optimizing your api key and"
-                                " or try again"
+                                f"Error running Dalle3: {error} try"
+                                " optimizing your api key and or try"
+                                " again"
+                            ),
+                            "red",
+                        )
+                    )
+                    print(
+                        colored(
+                            (
+                                "Error running Dalle3:"
+                                f" {error.http_status}"
                             ),
                             "red",
                         )
                     )
-                    print(colored(f"Error running Dalle3: {error.http_status}", "red"))
-                    print(colored(f"Error running Dalle3: {error.error}", "red"))
+                    print(
+                        colored(
+                            f"Error running Dalle3: {error.error}",
+                            "red",
+                        )
+                    )
                     raise error
 
     def _generate_uuid(self):
@@ -329,7 +360,9 @@ class Dalle3:
         """Str method for the Dalle3 class"""
         return f"Dalle3(image_url={self.image_url})"
 
-    @backoff.on_exception(backoff.expo, Exception, max_tries=max_retries)
+    @backoff.on_exception(
+        backoff.expo, Exception, max_tries=max_retries
+    )
     def rate_limited_call(self, task: str):
         """Rate limited call to the Dalle3 API"""
         return self.__call__(task)
diff --git a/swarms/models/distilled_whisperx.py b/swarms/models/distilled_whisperx.py
index 98b3660a..951dcd10 100644
--- a/swarms/models/distilled_whisperx.py
+++ b/swarms/models/distilled_whisperx.py
@@ -6,7 +6,11 @@ from typing import Union
 
 import torch
 from termcolor import colored
-from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor, pipeline
+from transformers import (
+    AutoModelForSpeechSeq2Seq,
+    AutoProcessor,
+    pipeline,
+)
 
 
 def async_retry(max_retries=3, exceptions=(Exception,), delay=1):
@@ -28,7 +32,10 @@ def async_retry(max_retries=3, exceptions=(Exception,), delay=1):
                     retries -= 1
                     if retries <= 0:
                         raise
-                    print(f"Retry after exception: {e}, Attempts remaining: {retries}")
+                    print(
+                        f"Retry after exception: {e}, Attempts"
+                        f" remaining: {retries}"
+                    )
                     await asyncio.sleep(delay)
 
         return wrapper
@@ -62,7 +69,11 @@ class DistilWhisperModel:
 
     def __init__(self, model_id="distil-whisper/distil-large-v2"):
         self.device = "cuda:0" if torch.cuda.is_available() else "cpu"
-        self.torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
+        self.torch_dtype = (
+            torch.float16
+            if torch.cuda.is_available()
+            else torch.float32
+        )
         self.model_id = model_id
         self.model = AutoModelForSpeechSeq2Seq.from_pretrained(
             model_id,
@@ -101,7 +112,9 @@ class DistilWhisperModel:
         :return: The transcribed text.
         """
         loop = asyncio.get_event_loop()
-        return await loop.run_in_executor(None, self.transcribe, inputs)
+        return await loop.run_in_executor(
+            None, self.transcribe, inputs
+        )
 
     def real_time_transcribe(self, audio_file_path, chunk_duration=5):
         """
@@ -119,17 +132,27 @@ class DistilWhisperModel:
         try:
             with torch.no_grad():
                 # Load the whole audio file, but process and transcribe it in chunks
-                audio_input = self.processor.audio_file_to_array(audio_file_path)
+                audio_input = self.processor.audio_file_to_array(
+                    audio_file_path
+                )
                 sample_rate = audio_input.sampling_rate
                 len(audio_input.array) / sample_rate
                 chunks = [
-                    audio_input.array[i : i + sample_rate * chunk_duration]
+                    audio_input.array[
+                        i : i + sample_rate * chunk_duration
+                    ]
                     for i in range(
-                        0, len(audio_input.array), sample_rate * chunk_duration
+                        0,
+                        len(audio_input.array),
+                        sample_rate * chunk_duration,
                     )
                 ]
 
-                print(colored("Starting real-time transcription...", "green"))
+                print(
+                    colored(
+                        "Starting real-time transcription...", "green"
+                    )
+                )
 
                 for i, chunk in enumerate(chunks):
                     # Process the current chunk
@@ -139,7 +162,9 @@ class DistilWhisperModel:
                         return_tensors="pt",
                         padding=True,
                     )
-                    processed_inputs = processed_inputs.input_values.to(self.device)
+                    processed_inputs = (
+                        processed_inputs.input_values.to(self.device)
+                    )
 
                     # Generate transcription for the chunk
                     logits = self.model.generate(processed_inputs)
@@ -149,7 +174,9 @@ class DistilWhisperModel:
 
                     # Print the chunk's transcription
                     print(
-                        colored(f"Chunk {i+1}/{len(chunks)}: ", "yellow")
+                        colored(
+                            f"Chunk {i+1}/{len(chunks)}: ", "yellow"
+                        )
                         + transcription
                     )
 
@@ -157,4 +184,9 @@ class DistilWhisperModel:
                     time.sleep(chunk_duration)
 
         except Exception as e:
-            print(colored(f"An error occurred during transcription: {e}", "red"))
+            print(
+                colored(
+                    f"An error occurred during transcription: {e}",
+                    "red",
+                )
+            )
diff --git a/swarms/models/eleven_labs.py b/swarms/models/eleven_labs.py
index 2fece5b6..2d55e864 100644
--- a/swarms/models/eleven_labs.py
+++ b/swarms/models/eleven_labs.py
@@ -13,7 +13,8 @@ def _import_elevenlabs() -> Any:
         import elevenlabs
     except ImportError as e:
         raise ImportError(
-            "Cannot import elevenlabs, please install `pip install elevenlabs`."
+            "Cannot import elevenlabs, please install `pip install"
+            " elevenlabs`."
         ) from e
     return elevenlabs
 
@@ -52,16 +53,18 @@ class ElevenLabsText2SpeechTool(BaseTool):
 
     name: str = "eleven_labs_text2speech"
     description: str = (
-        "A wrapper around Eleven Labs Text2Speech. "
-        "Useful for when you need to convert text to speech. "
-        "It supports multiple languages, including English, German, Polish, "
-        "Spanish, Italian, French, Portuguese, and Hindi. "
+        "A wrapper around Eleven Labs Text2Speech. Useful for when"
+        " you need to convert text to speech. It supports multiple"
+        " languages, including English, German, Polish, Spanish,"
+        " Italian, French, Portuguese, and Hindi. "
     )
 
     @root_validator(pre=True)
     def validate_environment(cls, values: Dict) -> Dict:
         """Validate that api key exists in environment."""
-        _ = get_from_dict_or_env(values, "eleven_api_key", "ELEVEN_API_KEY")
+        _ = get_from_dict_or_env(
+            values, "eleven_api_key", "ELEVEN_API_KEY"
+        )
 
         return values
 
@@ -79,7 +82,9 @@ class ElevenLabsText2SpeechTool(BaseTool):
                 f.write(speech)
             return f.name
         except Exception as e:
-            raise RuntimeError(f"Error while running ElevenLabsText2SpeechTool: {e}")
+            raise RuntimeError(
+                f"Error while running ElevenLabsText2SpeechTool: {e}"
+            )
 
     def play(self, speech_file: str) -> None:
         """Play the text as speech."""
@@ -93,12 +98,16 @@ class ElevenLabsText2SpeechTool(BaseTool):
         """Stream the text as speech as it is generated.
         Play the text in your speakers."""
         elevenlabs = _import_elevenlabs()
-        speech_stream = elevenlabs.generate(text=query, model=self.model, stream=True)
+        speech_stream = elevenlabs.generate(
+            text=query, model=self.model, stream=True
+        )
         elevenlabs.stream(speech_stream)
 
     def save(self, speech_file: str, path: str) -> None:
         """Save the speech file to a path."""
-        raise NotImplementedError("Saving not implemented for this tool.")
+        raise NotImplementedError(
+            "Saving not implemented for this tool."
+        )
 
     def __str__(self):
         return "ElevenLabsText2SpeechTool"
diff --git a/swarms/models/embeddings_base.py b/swarms/models/embeddings_base.py
index 6dd700c4..b0f5e22e 100644
--- a/swarms/models/embeddings_base.py
+++ b/swarms/models/embeddings_base.py
@@ -14,7 +14,9 @@ class Embeddings(ABC):
     def embed_query(self, text: str) -> List[float]:
         """Embed query text."""
 
-    async def aembed_documents(self, texts: List[str]) -> List[List[float]]:
+    async def aembed_documents(
+        self, texts: List[str]
+    ) -> List[List[float]]:
         """Embed search docs."""
         raise NotImplementedError
 
diff --git a/swarms/models/fast_vit_classes.json b/swarms/models/fast_vit_classes.json
deleted file mode 100644
index 57434253..00000000
--- a/swarms/models/fast_vit_classes.json
+++ /dev/null
@@ -1,1000 +0,0 @@
-["tench",
-"goldfish",
-"great white shark",
-"tiger shark",
-"hammerhead shark",
-"electric ray",
-"stingray",
-"cock",
-"hen",
-"ostrich",
-"brambling",
-"goldfinch",
-"house finch",
-"junco",
-"indigo bunting",
-"American robin",
-"bulbul",
-"jay",
-"magpie",
-"chickadee",
-"American dipper",
-"kite",
-"bald eagle",
-"vulture",
-"great grey owl",
-"fire salamander",
-"smooth newt",
-"newt",
-"spotted salamander",
-"axolotl",
-"American bullfrog",
-"tree frog",
-"tailed frog",
-"loggerhead sea turtle",
-"leatherback sea turtle",
-"mud turtle",
-"terrapin",
-"box turtle",
-"banded gecko",
-"green iguana",
-"Carolina anole",
-"desert grassland whiptail lizard",
-"agama",
-"frilled-necked lizard",
-"alligator lizard",
-"Gila monster",
-"European green lizard",
-"chameleon",
-"Komodo dragon",
-"Nile crocodile",
-"American alligator",
-"triceratops",
-"worm snake",
-"ring-necked snake",
-"eastern hog-nosed snake",
-"smooth green snake",
-"kingsnake",
-"garter snake",
-"water snake",
-"vine snake",
-"night snake",
-"boa constrictor",
-"African rock python",
-"Indian cobra",
-"green mamba",
-"sea snake",
-"Saharan horned viper",
-"eastern diamondback rattlesnake",
-"sidewinder",
-"trilobite",
-"harvestman",
-"scorpion",
-"yellow garden spider",
-"barn spider",
-"European garden spider",
-"southern black widow",
-"tarantula",
-"wolf spider",
-"tick",
-"centipede",
-"black grouse",
-"ptarmigan",
-"ruffed grouse",
-"prairie grouse",
-"peacock",
-"quail",
-"partridge",
-"grey parrot",
-"macaw",
-"sulphur-crested cockatoo",
-"lorikeet",
-"coucal",
-"bee eater",
-"hornbill",
-"hummingbird",
-"jacamar",
-"toucan",
-"duck",
-"red-breasted merganser",
-"goose",
-"black swan",
-"tusker",
-"echidna",
-"platypus",
-"wallaby",
-"koala",
-"wombat",
-"jellyfish",
-"sea anemone",
-"brain coral",
-"flatworm",
-"nematode",
-"conch",
-"snail",
-"slug",
-"sea slug",
-"chiton",
-"chambered nautilus",
-"Dungeness crab",
-"rock crab",
-"fiddler crab",
-"red king crab",
-"American lobster",
-"spiny lobster",
-"crayfish",
-"hermit crab",
-"isopod",
-"white stork",
-"black stork",
-"spoonbill",
-"flamingo",
-"little blue heron",
-"great egret",
-"bittern",
-"crane (bird)",
-"limpkin",
-"common gallinule",
-"American coot",
-"bustard",
-"ruddy turnstone",
-"dunlin",
-"common redshank",
-"dowitcher",
-"oystercatcher",
-"pelican",
-"king penguin",
-"albatross",
-"grey whale",
-"killer whale",
-"dugong",
-"sea lion",
-"Chihuahua",
-"Japanese Chin",
-"Maltese",
-"Pekingese",
-"Shih Tzu",
-"King Charles Spaniel",
-"Papillon",
-"toy terrier",
-"Rhodesian Ridgeback",
-"Afghan Hound",
-"Basset Hound",
-"Beagle",
-"Bloodhound",
-"Bluetick Coonhound",
-"Black and Tan Coonhound",
-"Treeing Walker Coonhound",
-"English foxhound",
-"Redbone Coonhound",
-"borzoi",
-"Irish Wolfhound",
-"Italian Greyhound",
-"Whippet",
-"Ibizan Hound",
-"Norwegian Elkhound",
-"Otterhound",
-"Saluki",
-"Scottish Deerhound",
-"Weimaraner",
-"Staffordshire Bull Terrier",
-"American Staffordshire Terrier",
-"Bedlington Terrier",
-"Border Terrier",
-"Kerry Blue Terrier",
-"Irish Terrier",
-"Norfolk Terrier",
-"Norwich Terrier",
-"Yorkshire Terrier",
-"Wire Fox Terrier",
-"Lakeland Terrier",
-"Sealyham Terrier",
-"Airedale Terrier",
-"Cairn Terrier",
-"Australian Terrier",
-"Dandie Dinmont Terrier",
-"Boston Terrier",
-"Miniature Schnauzer",
-"Giant Schnauzer",
-"Standard Schnauzer",
-"Scottish Terrier",
-"Tibetan Terrier",
-"Australian Silky Terrier",
-"Soft-coated Wheaten Terrier",
-"West Highland White Terrier",
-"Lhasa Apso",
-"Flat-Coated Retriever",
-"Curly-coated Retriever",
-"Golden Retriever",
-"Labrador Retriever",
-"Chesapeake Bay Retriever",
-"German Shorthaired Pointer",
-"Vizsla",
-"English Setter",
-"Irish Setter",
-"Gordon Setter",
-"Brittany Spaniel",
-"Clumber Spaniel",
-"English Springer Spaniel",
-"Welsh Springer Spaniel",
-"Cocker Spaniels",
-"Sussex Spaniel",
-"Irish Water Spaniel",
-"Kuvasz",
-"Schipperke",
-"Groenendael",
-"Malinois",
-"Briard",
-"Australian Kelpie",
-"Komondor",
-"Old English Sheepdog",
-"Shetland Sheepdog",
-"collie",
-"Border Collie",
-"Bouvier des Flandres",
-"Rottweiler",
-"German Shepherd Dog",
-"Dobermann",
-"Miniature Pinscher",
-"Greater Swiss Mountain Dog",
-"Bernese Mountain Dog",
-"Appenzeller Sennenhund",
-"Entlebucher Sennenhund",
-"Boxer",
-"Bullmastiff",
-"Tibetan Mastiff",
-"French Bulldog",
-"Great Dane",
-"St. Bernard",
-"husky",
-"Alaskan Malamute",
-"Siberian Husky",
-"Dalmatian",
-"Affenpinscher",
-"Basenji",
-"pug",
-"Leonberger",
-"Newfoundland",
-"Pyrenean Mountain Dog",
-"Samoyed",
-"Pomeranian",
-"Chow Chow",
-"Keeshond",
-"Griffon Bruxellois",
-"Pembroke Welsh Corgi",
-"Cardigan Welsh Corgi",
-"Toy Poodle",
-"Miniature Poodle",
-"Standard Poodle",
-"Mexican hairless dog",
-"grey wolf",
-"Alaskan tundra wolf",
-"red wolf",
-"coyote",
-"dingo",
-"dhole",
-"African wild dog",
-"hyena",
-"red fox",
-"kit fox",
-"Arctic fox",
-"grey fox",
-"tabby cat",
-"tiger cat",
-"Persian cat",
-"Siamese cat",
-"Egyptian Mau",
-"cougar",
-"lynx",
-"leopard",
-"snow leopard",
-"jaguar",
-"lion",
-"tiger",
-"cheetah",
-"brown bear",
-"American black bear",
-"polar bear",
-"sloth bear",
-"mongoose",
-"meerkat",
-"tiger beetle",
-"ladybug",
-"ground beetle",
-"longhorn beetle",
-"leaf beetle",
-"dung beetle",
-"rhinoceros beetle",
-"weevil",
-"fly",
-"bee",
-"ant",
-"grasshopper",
-"cricket",
-"stick insect",
-"cockroach",
-"mantis",
-"cicada",
-"leafhopper",
-"lacewing",
-"dragonfly",
-"damselfly",
-"red admiral",
-"ringlet",
-"monarch butterfly",
-"small white",
-"sulphur butterfly",
-"gossamer-winged butterfly",
-"starfish",
-"sea urchin",
-"sea cucumber",
-"cottontail rabbit",
-"hare",
-"Angora rabbit",
-"hamster",
-"porcupine",
-"fox squirrel",
-"marmot",
-"beaver",
-"guinea pig",
-"common sorrel",
-"zebra",
-"pig",
-"wild boar",
-"warthog",
-"hippopotamus",
-"ox",
-"water buffalo",
-"bison",
-"ram",
-"bighorn sheep",
-"Alpine ibex",
-"hartebeest",
-"impala",
-"gazelle",
-"dromedary",
-"llama",
-"weasel",
-"mink",
-"European polecat",
-"black-footed ferret",
-"otter",
-"skunk",
-"badger",
-"armadillo",
-"three-toed sloth",
-"orangutan",
-"gorilla",
-"chimpanzee",
-"gibbon",
-"siamang",
-"guenon",
-"patas monkey",
-"baboon",
-"macaque",
-"langur",
-"black-and-white colobus",
-"proboscis monkey",
-"marmoset",
-"white-headed capuchin",
-"howler monkey",
-"titi",
-"Geoffroy's spider monkey",
-"common squirrel monkey",
-"ring-tailed lemur",
-"indri",
-"Asian elephant",
-"African bush elephant",
-"red panda",
-"giant panda",
-"snoek",
-"eel",
-"coho salmon",
-"rock beauty",
-"clownfish",
-"sturgeon",
-"garfish",
-"lionfish",
-"pufferfish",
-"abacus",
-"abaya",
-"academic gown",
-"accordion",
-"acoustic guitar",
-"aircraft carrier",
-"airliner",
-"airship",
-"altar",
-"ambulance",
-"amphibious vehicle",
-"analog clock",
-"apiary",
-"apron",
-"waste container",
-"assault rifle",
-"backpack",
-"bakery",
-"balance beam",
-"balloon",
-"ballpoint pen",
-"Band-Aid",
-"banjo",
-"baluster",
-"barbell",
-"barber chair",
-"barbershop",
-"barn",
-"barometer",
-"barrel",
-"wheelbarrow",
-"baseball",
-"basketball",
-"bassinet",
-"bassoon",
-"swimming cap",
-"bath towel",
-"bathtub",
-"station wagon",
-"lighthouse",
-"beaker",
-"military cap",
-"beer bottle",
-"beer glass",
-"bell-cot",
-"bib",
-"tandem bicycle",
-"bikini",
-"ring binder",
-"binoculars",
-"birdhouse",
-"boathouse",
-"bobsleigh",
-"bolo tie",
-"poke bonnet",
-"bookcase",
-"bookstore",
-"bottle cap",
-"bow",
-"bow tie",
-"brass",
-"bra",
-"breakwater",
-"breastplate",
-"broom",
-"bucket",
-"buckle",
-"bulletproof vest",
-"high-speed train",
-"butcher shop",
-"taxicab",
-"cauldron",
-"candle",
-"cannon",
-"canoe",
-"can opener",
-"cardigan",
-"car mirror",
-"carousel",
-"tool kit",
-"carton",
-"car wheel",
-"automated teller machine",
-"cassette",
-"cassette player",
-"castle",
-"catamaran",
-"CD player",
-"cello",
-"mobile phone",
-"chain",
-"chain-link fence",
-"chain mail",
-"chainsaw",
-"chest",
-"chiffonier",
-"chime",
-"china cabinet",
-"Christmas stocking",
-"church",
-"movie theater",
-"cleaver",
-"cliff dwelling",
-"cloak",
-"clogs",
-"cocktail shaker",
-"coffee mug",
-"coffeemaker",
-"coil",
-"combination lock",
-"computer keyboard",
-"confectionery store",
-"container ship",
-"convertible",
-"corkscrew",
-"cornet",
-"cowboy boot",
-"cowboy hat",
-"cradle",
-"crane (machine)",
-"crash helmet",
-"crate",
-"infant bed",
-"Crock Pot",
-"croquet ball",
-"crutch",
-"cuirass",
-"dam",
-"desk",
-"desktop computer",
-"rotary dial telephone",
-"diaper",
-"digital clock",
-"digital watch",
-"dining table",
-"dishcloth",
-"dishwasher",
-"disc brake",
-"dock",
-"dog sled",
-"dome",
-"doormat",
-"drilling rig",
-"drum",
-"drumstick",
-"dumbbell",
-"Dutch oven",
-"electric fan",
-"electric guitar",
-"electric locomotive",
-"entertainment center",
-"envelope",
-"espresso machine",
-"face powder",
-"feather boa",
-"filing cabinet",
-"fireboat",
-"fire engine",
-"fire screen sheet",
-"flagpole",
-"flute",
-"folding chair",
-"football helmet",
-"forklift",
-"fountain",
-"fountain pen",
-"four-poster bed",
-"freight car",
-"French horn",
-"frying pan",
-"fur coat",
-"garbage truck",
-"gas mask",
-"gas pump",
-"goblet",
-"go-kart",
-"golf ball",
-"golf cart",
-"gondola",
-"gong",
-"gown",
-"grand piano",
-"greenhouse",
-"grille",
-"grocery store",
-"guillotine",
-"barrette",
-"hair spray",
-"half-track",
-"hammer",
-"hamper",
-"hair dryer",
-"hand-held computer",
-"handkerchief",
-"hard disk drive",
-"harmonica",
-"harp",
-"harvester",
-"hatchet",
-"holster",
-"home theater",
-"honeycomb",
-"hook",
-"hoop skirt",
-"horizontal bar",
-"horse-drawn vehicle",
-"hourglass",
-"iPod",
-"clothes iron",
-"jack-o'-lantern",
-"jeans",
-"jeep",
-"T-shirt",
-"jigsaw puzzle",
-"pulled rickshaw",
-"joystick",
-"kimono",
-"knee pad",
-"knot",
-"lab coat",
-"ladle",
-"lampshade",
-"laptop computer",
-"lawn mower",
-"lens cap",
-"paper knife",
-"library",
-"lifeboat",
-"lighter",
-"limousine",
-"ocean liner",
-"lipstick",
-"slip-on shoe",
-"lotion",
-"speaker",
-"loupe",
-"sawmill",
-"magnetic compass",
-"mail bag",
-"mailbox",
-"tights",
-"tank suit",
-"manhole cover",
-"maraca",
-"marimba",
-"mask",
-"match",
-"maypole",
-"maze",
-"measuring cup",
-"medicine chest",
-"megalith",
-"microphone",
-"microwave oven",
-"military uniform",
-"milk can",
-"minibus",
-"miniskirt",
-"minivan",
-"missile",
-"mitten",
-"mixing bowl",
-"mobile home",
-"Model T",
-"modem",
-"monastery",
-"monitor",
-"moped",
-"mortar",
-"square academic cap",
-"mosque",
-"mosquito net",
-"scooter",
-"mountain bike",
-"tent",
-"computer mouse",
-"mousetrap",
-"moving van",
-"muzzle",
-"nail",
-"neck brace",
-"necklace",
-"nipple",
-"notebook computer",
-"obelisk",
-"oboe",
-"ocarina",
-"odometer",
-"oil filter",
-"organ",
-"oscilloscope",
-"overskirt",
-"bullock cart",
-"oxygen mask",
-"packet",
-"paddle",
-"paddle wheel",
-"padlock",
-"paintbrush",
-"pajamas",
-"palace",
-"pan flute",
-"paper towel",
-"parachute",
-"parallel bars",
-"park bench",
-"parking meter",
-"passenger car",
-"patio",
-"payphone",
-"pedestal",
-"pencil case",
-"pencil sharpener",
-"perfume",
-"Petri dish",
-"photocopier",
-"plectrum",
-"Pickelhaube",
-"picket fence",
-"pickup truck",
-"pier",
-"piggy bank",
-"pill bottle",
-"pillow",
-"ping-pong ball",
-"pinwheel",
-"pirate ship",
-"pitcher",
-"hand plane",
-"planetarium",
-"plastic bag",
-"plate rack",
-"plow",
-"plunger",
-"Polaroid camera",
-"pole",
-"police van",
-"poncho",
-"billiard table",
-"soda bottle",
-"pot",
-"potter's wheel",
-"power drill",
-"prayer rug",
-"printer",
-"prison",
-"projectile",
-"projector",
-"hockey puck",
-"punching bag",
-"purse",
-"quill",
-"quilt",
-"race car",
-"racket",
-"radiator",
-"radio",
-"radio telescope",
-"rain barrel",
-"recreational vehicle",
-"reel",
-"reflex camera",
-"refrigerator",
-"remote control",
-"restaurant",
-"revolver",
-"rifle",
-"rocking chair",
-"rotisserie",
-"eraser",
-"rugby ball",
-"ruler",
-"running shoe",
-"safe",
-"safety pin",
-"salt shaker",
-"sandal",
-"sarong",
-"saxophone",
-"scabbard",
-"weighing scale",
-"school bus",
-"schooner",
-"scoreboard",
-"CRT screen",
-"screw",
-"screwdriver",
-"seat belt",
-"sewing machine",
-"shield",
-"shoe store",
-"shoji",
-"shopping basket",
-"shopping cart",
-"shovel",
-"shower cap",
-"shower curtain",
-"ski",
-"ski mask",
-"sleeping bag",
-"slide rule",
-"sliding door",
-"slot machine",
-"snorkel",
-"snowmobile",
-"snowplow",
-"soap dispenser",
-"soccer ball",
-"sock",
-"solar thermal collector",
-"sombrero",
-"soup bowl",
-"space bar",
-"space heater",
-"space shuttle",
-"spatula",
-"motorboat",
-"spider web",
-"spindle",
-"sports car",
-"spotlight",
-"stage",
-"steam locomotive",
-"through arch bridge",
-"steel drum",
-"stethoscope",
-"scarf",
-"stone wall",
-"stopwatch",
-"stove",
-"strainer",
-"tram",
-"stretcher",
-"couch",
-"stupa",
-"submarine",
-"suit",
-"sundial",
-"sunglass",
-"sunglasses",
-"sunscreen",
-"suspension bridge",
-"mop",
-"sweatshirt",
-"swimsuit",
-"swing",
-"switch",
-"syringe",
-"table lamp",
-"tank",
-"tape player",
-"teapot",
-"teddy bear",
-"television",
-"tennis ball",
-"thatched roof",
-"front curtain",
-"thimble",
-"threshing machine",
-"throne",
-"tile roof",
-"toaster",
-"tobacco shop",
-"toilet seat",
-"torch",
-"totem pole",
-"tow truck",
-"toy store",
-"tractor",
-"semi-trailer truck",
-"tray",
-"trench coat",
-"tricycle",
-"trimaran",
-"tripod",
-"triumphal arch",
-"trolleybus",
-"trombone",
-"tub",
-"turnstile",
-"typewriter keyboard",
-"umbrella",
-"unicycle",
-"upright piano",
-"vacuum cleaner",
-"vase",
-"vault",
-"velvet",
-"vending machine",
-"vestment",
-"viaduct",
-"violin",
-"volleyball",
-"waffle iron",
-"wall clock",
-"wallet",
-"wardrobe",
-"military aircraft",
-"sink",
-"washing machine",
-"water bottle",
-"water jug",
-"water tower",
-"whiskey jug",
-"whistle",
-"wig",
-"window screen",
-"window shade",
-"Windsor tie",
-"wine bottle",
-"wing",
-"wok",
-"wooden spoon",
-"wool",
-"split-rail fence",
-"shipwreck",
-"yawl",
-"yurt",
-"website",
-"comic book",
-"crossword",
-"traffic sign",
-"traffic light",
-"dust jacket",
-"menu",
-"plate",
-"guacamole",
-"consomme",
-"hot pot",
-"trifle",
-"ice cream",
-"ice pop",
-"baguette",
-"bagel",
-"pretzel",
-"cheeseburger",
-"hot dog",
-"mashed potato",
-"cabbage",
-"broccoli",
-"cauliflower",
-"zucchini",
-"spaghetti squash",
-"acorn squash",
-"butternut squash",
-"cucumber",
-"artichoke",
-"bell pepper",
-"cardoon",
-"mushroom",
-"Granny Smith",
-"strawberry",
-"orange",
-"lemon",
-"fig",
-"pineapple",
-"banana",
-"jackfruit",
-"custard apple",
-"pomegranate",
-"hay",
-"carbonara",
-"chocolate syrup",
-"dough",
-"meatloaf",
-"pizza",
-"pot pie",
-"burrito",
-"red wine",
-"espresso",
-"cup",
-"eggnog",
-"alp",
-"bubble",
-"cliff",
-"coral reef",
-"geyser",
-"lakeshore",
-"promontory",
-"shoal",
-"seashore",
-"valley",
-"volcano",
-"baseball player",
-"bridegroom",
-"scuba diver",
-"rapeseed",
-"daisy",
-"yellow lady's slipper",
-"corn",
-"acorn",
-"rose hip",
-"horse chestnut seed",
-"coral fungus",
-"agaric",
-"gyromitra",
-"stinkhorn mushroom",
-"earth star",
-"hen-of-the-woods",
-"bolete",
-"ear of corn",
-"toilet paper"]
\ No newline at end of file
diff --git a/swarms/models/fastvit.py b/swarms/models/fastvit.py
index d0478777..a6fc31f8 100644
--- a/swarms/models/fastvit.py
+++ b/swarms/models/fastvit.py
@@ -10,7 +10,9 @@ from pydantic import BaseModel, StrictFloat, StrictInt, validator
 DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
 # Load the classes for image classification
-with open(os.path.join(os.path.dirname(__file__), "fast_vit_classes.json")) as f:
+with open(
+    os.path.join(os.path.dirname(__file__), "fast_vit_classes.json")
+) as f:
     FASTVIT_IMAGENET_1K_CLASSES = json.load(f)
 
 
@@ -20,7 +22,9 @@ class ClassificationResult(BaseModel):
 
     @validator("class_id", "confidence", pre=True, each_item=True)
     def check_list_contents(cls, v):
-        assert isinstance(v, int) or isinstance(v, float), "must be integer or float"
+        assert isinstance(v, int) or isinstance(
+            v, float
+        ), "must be integer or float"
         return v
 
 
@@ -50,7 +54,9 @@ class FastViT:
             "hf_hub:timm/fastvit_s12.apple_in1k", pretrained=True
         ).to(DEVICE)
         data_config = timm.data.resolve_model_data_config(self.model)
-        self.transforms = timm.data.create_transform(**data_config, is_training=False)
+        self.transforms = timm.data.create_transform(
+            **data_config, is_training=False
+        )
         self.model.eval()
 
     def __call__(
@@ -77,4 +83,6 @@ class FastViT:
         top_classes = top_classes.cpu().numpy().tolist()
         # top_class_labels = [FASTVIT_IMAGENET_1K_CLASSES[i] for i in top_classes] # Uncomment if class labels are needed
 
-        return ClassificationResult(class_id=top_classes, confidence=top_probs)
+        return ClassificationResult(
+            class_id=top_classes, confidence=top_probs
+        )
diff --git a/swarms/models/fuyu.py b/swarms/models/fuyu.py
index 02ab3a25..c1e51199 100644
--- a/swarms/models/fuyu.py
+++ b/swarms/models/fuyu.py
@@ -43,10 +43,14 @@ class Fuyu:
         self.device_map = device_map
         self.max_new_tokens = max_new_tokens
 
-        self.tokenizer = AutoTokenizer.from_pretrained(pretrained_path)
+        self.tokenizer = AutoTokenizer.from_pretrained(
+            pretrained_path
+        )
         self.image_processor = FuyuImageProcessor()
         self.processor = FuyuProcessor(
-            image_processor=self.image_processor, tokenizer=self.tokenizer, **kwargs
+            image_processor=self.image_processor,
+            tokenizer=self.tokenizer,
+            **kwargs,
         )
         self.model = FuyuForCausalLM.from_pretrained(
             pretrained_path,
@@ -61,25 +65,31 @@ class Fuyu:
 
     def __call__(self, text: str, img: str):
         """Call the model with text and img paths"""
-        image_pil = Image.open(img)
+        img = self.get_img(img)
         model_inputs = self.processor(
-            text=text, images=[image_pil], device=self.device_map
+            text=text, images=[img], device=self.device_map
         )
 
         for k, v in model_inputs.items():
             model_inputs[k] = v.to(self.device_map)
 
-        output = self.model.generate(**model_inputs, max_new_tokens=self.max_new_tokens)
-        text = self.processor.batch_decode(output[:, -7:], skip_special_tokens=True)
+        output = self.model.generate(
+            **model_inputs, max_new_tokens=self.max_new_tokens
+        )
+        text = self.processor.batch_decode(
+            output[:, -7:], skip_special_tokens=True
+        )
         return print(str(text))
 
-    def get_img_from_web(self, img_url: str):
+    def get_img_from_web(self, img: str):
         """Get the image from the web"""
         try:
-            response = requests.get(img_url)
+            response = requests.get(img)
             response.raise_for_status()
             image_pil = Image.open(BytesIO(response.content))
             return image_pil
         except requests.RequestException as error:
-            print(f"Error fetching image from {img_url} and error: {error}")
+            print(
+                f"Error fetching image from {img} and error: {error}"
+            )
             return None
diff --git a/swarms/models/gpt4_vision_api.py b/swarms/models/gpt4_vision_api.py
new file mode 100644
index 00000000..cd6e5ddb
--- /dev/null
+++ b/swarms/models/gpt4_vision_api.py
@@ -0,0 +1,473 @@
+import asyncio
+import base64
+import concurrent.futures
+import json
+import logging
+import os
+from concurrent.futures import ThreadPoolExecutor
+from typing import List, Optional, Tuple
+
+import aiohttp
+import requests
+from dotenv import load_dotenv
+from termcolor import colored
+
+try:
+    import cv2
+except ImportError:
+    print(
+        "OpenCV not installed. Please install OpenCV to use this"
+        " model."
+    )
+    raise ImportError
+
+# Load environment variables
+load_dotenv()
+openai_api_key = os.getenv("OPENAI_API_KEY")
+
+
+gpt4_vision_system_prompt = """
+You are an multi-modal autonomous agent. You are given a task and an image. You must generate a response to the task and image.
+
+"""
+
+
+class GPT4VisionAPI:
+    """
+    GPT-4 Vision API
+
+    This class is a wrapper for the OpenAI API. It is used to run the GPT-4 Vision model.
+
+    Parameters
+    ----------
+    openai_api_key : str
+        The OpenAI API key. Defaults to the OPENAI_API_KEY environment variable.
+    max_tokens : int
+        The maximum number of tokens to generate. Defaults to 300.
+
+
+    Methods
+    -------
+    encode_image(img: str)
+        Encode image to base64.
+    run(task: str, img: str)
+        Run the model.
+    __call__(task: str, img: str)
+        Run the model.
+
+    Examples:
+    ---------
+    >>> from swarms.models import GPT4VisionAPI
+    >>> llm = GPT4VisionAPI()
+    >>> task = "What is the color of the object?"
+    >>> img = "https://i.imgur.com/2M2ZGwC.jpeg"
+    >>> llm.run(task, img)
+
+
+    """
+
+    def __init__(
+        self,
+        openai_api_key: str = openai_api_key,
+        model_name: str = "gpt-4-vision-preview",
+        logging_enabled: bool = False,
+        max_workers: int = 10,
+        max_tokens: str = 300,
+        openai_proxy: str = "https://api.openai.com/v1/chat/completions",
+        beautify: bool = False,
+        streaming_enabled: Optional[bool] = False,
+        meta_prompt: Optional[bool] = False,
+        system_prompt: Optional[str] = gpt4_vision_system_prompt,
+        *args,
+        **kwargs,
+    ):
+        super().__init__()
+        self.openai_api_key = openai_api_key
+        self.logging_enabled = logging_enabled
+        self.model_name = model_name
+        self.max_workers = max_workers
+        self.max_tokens = max_tokens
+        self.openai_proxy = openai_proxy
+        self.beautify = beautify
+        self.streaming_enabled = streaming_enabled
+        self.meta_prompt = meta_prompt
+        self.system_prompt = system_prompt
+
+        if self.logging_enabled:
+            logging.basicConfig(level=logging.DEBUG)
+        else:
+            # Disable debug logs for requests and urllib3
+            logging.getLogger("requests").setLevel(logging.WARNING)
+            logging.getLogger("urllib3").setLevel(logging.WARNING)
+
+        if self.meta_prompt:
+            self.system_prompt = self.meta_prompt_init()
+
+    def encode_image(self, img: str):
+        """Encode image to base64."""
+        if not os.path.exists(img):
+            print(f"Image file not found: {img}")
+            return None
+
+        with open(img, "rb") as image_file:
+            return base64.b64encode(image_file.read()).decode("utf-8")
+
+    def download_img_then_encode(self, img: str):
+        """Download image from URL then encode image to base64 using requests"""
+        pass
+
+    # Function to handle vision tasks
+    def run(self, img, task):
+        """Run the model."""
+        try:
+            base64_image = self.encode_image(img)
+            headers = {
+                "Content-Type": "application/json",
+                "Authorization": f"Bearer {self.openai_api_key}",
+            }
+            payload = {
+                "model": self.model_name,
+                "messages": [
+                    {
+                        "role": "system",
+                        "content": [self.system_prompt],
+                    },
+                    {
+                        "role": "user",
+                        "content": [
+                            {"type": "text", "text": task},
+                            {
+                                "type": "image_url",
+                                "image_url": {
+                                    "url": f"data:image/jpeg;base64,{base64_image}"
+                                },
+                            },
+                        ],
+                    },
+                ],
+                "max_tokens": self.max_tokens,
+            }
+            response = requests.post(
+                self.openai_proxy, headers=headers, json=payload
+            )
+
+            out = response.json()
+            if "choices" in out and out["choices"]:
+                content = (
+                    out["choices"][0]
+                    .get("message", {})
+                    .get("content", None)
+                )
+                return content
+            else:
+                print("No valid response in 'choices'")
+                return None
+
+        except Exception as error:
+            print(f"Error with the request: {error}")
+            return None
+
+    def video_prompt(self, frames):
+        """
+        SystemPrompt is a class that generates a prompt for the user to respond to.
+        The prompt is generated based on the current state of the system.
+
+        Parameters
+        ----------
+        frames : list
+            A list of base64 frames
+
+        Returns
+        -------
+        PROMPT : str
+            The system prompt
+
+        Examples
+        --------
+
+        >>> from swarms.models import GPT4VisionAPI
+        >>> llm = GPT4VisionAPI()
+        >>> video = "video.mp4"
+        >>> base64_frames = llm.process_video(video)
+        >>> prompt = llm.video_prompt(base64_frames)
+        >>> print(prompt)
+
+        """
+        PROMPT = f"""
+        These are frames from a video that I want to upload. Generate a compelling description that I can upload along with the video:
+        
+        {frames}
+        """
+        return PROMPT
+
+    def stream_response(self, content: str):
+        """Stream the response of the output
+
+        Args:
+            content (str): _description_
+        """
+        for chunk in content:
+            print(chunk)
+
+    def process_video(self, video: str):
+        """
+        Process a video into a list of base64 frames
+
+        Parameters
+        ----------
+        video : str
+            The path to the video file
+
+        Returns
+        -------
+        base64_frames : list
+            A list of base64 frames
+
+        Examples
+        --------
+        >>> from swarms.models import GPT4VisionAPI
+        >>> llm = GPT4VisionAPI()
+        >>> video = "video.mp4"
+        >>> base64_frames = llm.process_video(video)
+
+        """
+        video = cv2.VideoCapture(video)
+
+        base64_frames = []
+        while video.isOpened():
+            success, frame = video.read()
+            if not success:
+                break
+            _, buffer = cv2.imencode(".jpg", frame)
+            base64_frames.append(
+                base64.b64encode(buffer).decode("utf-8")
+            )
+
+        video.release()
+        print(len(base64_frames), "frames read.")
+
+        for img in base64_frames:
+            base64.b64decode(img.encode("utf-8"))
+
+    def __call__(
+        self,
+        task: Optional[str] = None,
+        img: Optional[str] = None,
+        *args,
+        **kwargs,
+    ):
+        """Run the model."""
+        try:
+            base64_image = self.encode_image(img)
+            headers = {
+                "Content-Type": "application/json",
+                "Authorization": f"Bearer {openai_api_key}",
+            }
+            payload = {
+                "model": self.model_name,
+                "messages": [
+                    {
+                        "role": "system",
+                        "content": [self.system_prompt],
+                    },
+                    {
+                        "role": "user",
+                        "content": [
+                            {"type": "text", "text": task},
+                            {
+                                "type": "image_url",
+                                "image_url": {
+                                    "url": f"data:image/jpeg;base64,{base64_image}"
+                                },
+                            },
+                        ],
+                    },
+                ],
+                "max_tokens": self.max_tokens,
+            }
+            response = requests.post(
+                self.openai_proxy,
+                headers=headers,
+                json=payload,
+            )
+
+            out = response.json()
+            content = out["choices"][0]["message"]["content"]
+
+            if self.streaming_enabled:
+                content = self.stream_response(content)
+            else:
+                pass
+
+            if self.beautify:
+                content = colored(content, "cyan")
+                print(content)
+            else:
+                print(content)
+
+        except Exception as error:
+            print(f"Error with the request: {error}")
+            raise error
+
+    def run_many(
+        self,
+        tasks: List[str],
+        imgs: List[str],
+    ):
+        """
+        Run the model on multiple tasks and images all at once using concurrent
+
+        Args:
+            tasks (List[str]): List of tasks
+            imgs (List[str]): List of image paths
+
+        Returns:
+            List[str]: List of responses
+
+
+        """
+        # Instantiate the thread pool executor
+        with ThreadPoolExecutor(
+            max_workers=self.max_workers
+        ) as executor:
+            results = executor.map(self.run, tasks, imgs)
+
+        # Print the results for debugging
+        for result in results:
+            print(result)
+
+        return list(results)
+
+    async def arun(
+        self,
+        task: Optional[str] = None,
+        img: Optional[str] = None,
+    ):
+        """
+        Asynchronously run the model
+
+        Overview:
+        ---------
+        This method is used to asynchronously run the model. It is used to run the model
+        on a single task and image.
+
+        Parameters:
+        ----------
+        task : str
+            The task to run the model on.
+        img : str
+            The image to run the task on
+
+        """
+        try:
+            base64_image = self.encode_image(img)
+            headers = {
+                "Content-Type": "application/json",
+                "Authorization": f"Bearer {openai_api_key}",
+            }
+            payload = {
+                "model": "gpt-4-vision-preview",
+                "messages": [
+                    {
+                        "role": "user",
+                        "content": [
+                            {"type": "text", "text": task},
+                            {
+                                "type": "image_url",
+                                "image_url": {
+                                    "url": f"data:image/jpeg;base64,{base64_image}"
+                                },
+                            },
+                        ],
+                    }
+                ],
+                "max_tokens": self.max_tokens,
+            }
+            async with aiohttp.ClientSession() as session:
+                async with session.post(
+                    self.openai_proxy,
+                    headers=headers,
+                    data=json.dumps(payload),
+                ) as response:
+                    out = await response.json()
+                    content = out["choices"][0]["message"]["content"]
+                    print(content)
+        except Exception as error:
+            print(f"Error with the request {error}")
+            raise error
+
+    def run_batch(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
+        """Process a batch of tasks and images"""
+        with concurrent.futures.ThreadPoolExecutor() as executor:
+            futures = [
+                executor.submit(self.run, task, img)
+                for task, img in tasks_images
+            ]
+            results = [future.result() for future in futures]
+        return results
+
+    async def run_batch_async(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
+        """Process a batch of tasks and images asynchronously"""
+        loop = asyncio.get_event_loop()
+        futures = [
+            loop.run_in_executor(None, self.run, task, img)
+            for task, img in tasks_images
+        ]
+        return await asyncio.gather(*futures)
+
+    async def run_batch_async_with_retries(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
+        """Process a batch of tasks and images asynchronously with retries"""
+        loop = asyncio.get_event_loop()
+        futures = [
+            loop.run_in_executor(
+                None, self.run_with_retries, task, img
+            )
+            for task, img in tasks_images
+        ]
+        return await asyncio.gather(*futures)
+
+    def health_check(self):
+        """Health check for the GPT4Vision model"""
+        try:
+            response = requests.get(
+                "https://api.openai.com/v1/engines"
+            )
+            return response.status_code == 200
+        except requests.RequestException as error:
+            print(f"Health check failed: {error}")
+            return False
+
+    def print_dashboard(self):
+        dashboard = print(
+            colored(
+                f"""
+            GPT4Vision Dashboard
+            -------------------
+            Model: {self.model_name}
+            Max Workers: {self.max_workers}
+            OpenAIProxy: {self.openai_proxy}
+            """,
+                "green",
+            )
+        )
+        return dashboard
+
+    # def meta_prompt_init(self):
+    #     """Meta Prompt
+
+    #     Returns:
+    #         _type_: _description_
+    #     """
+    #     META_PROMPT = """
+    #     For any labels or markings on an image that you reference in your response, please
+    #     enclose them in square brackets ([]) and list them explicitly. Do not use ranges; for
+    #     example, instead of '1 - 4', list as '[1], [2], [3], [4]'. These labels could be
+    #     numbers or letters and typically correspond to specific segments or parts of the image.
+    #     """
+    #     return META_PROMPT
diff --git a/swarms/models/gpt4v.py b/swarms/models/gpt4v.py
index 8411cb14..43eff12d 100644
--- a/swarms/models/gpt4v.py
+++ b/swarms/models/gpt4v.py
@@ -65,7 +65,9 @@ class GPT4Vision:
     model: str = "gpt-4-vision-preview"
     backoff_factor: float = 2.0
     timeout_seconds: int = 10
-    openai_api_key: Optional[str] = None or os.getenv("OPENAI_API_KEY")
+    openai_api_key: Optional[str] = None or os.getenv(
+        "OPENAI_API_KEY"
+    )
     # 'Low' or 'High' for respesctively fast or high quality, but high more token usage
     quality: str = "low"
     # Max tokens to use for the API request, the maximum might be 3,000 but we don't know
@@ -131,9 +133,14 @@ class GPT4Vision:
             return out
         except openai.OpenAIError as e:
             # logger.error(f"OpenAI API error: {e}")
-            return f"OpenAI API error: Could not process the image. {e}"
+            return (
+                f"OpenAI API error: Could not process the image. {e}"
+            )
         except Exception as e:
-            return f"Unexpected error occurred while processing the image. {e}"
+            return (
+                "Unexpected error occurred while processing the"
+                f" image. {e}"
+            )
 
     def clean_output(self, output: str):
         # Regex pattern to find the Choice object representation in the output
@@ -182,20 +189,30 @@ class GPT4Vision:
             return print(response.choices[0])
         except openai.OpenAIError as e:
             # logger.error(f"OpenAI API error: {e}")
-            return f"OpenAI API error: Could not process the image. {e}"
+            return (
+                f"OpenAI API error: Could not process the image. {e}"
+            )
         except Exception as e:
-            return f"Unexpected error occurred while processing the image. {e}"
+            return (
+                "Unexpected error occurred while processing the"
+                f" image. {e}"
+            )
 
-    def run_batch(self, tasks_images: List[Tuple[str, str]]) -> List[str]:
+    def run_batch(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
         """Process a batch of tasks and images"""
         with concurrent.futures.ThreadPoolExecutor() as executor:
             futures = [
-                executor.submit(self.run, task, img) for task, img in tasks_images
+                executor.submit(self.run, task, img)
+                for task, img in tasks_images
             ]
             results = [future.result() for future in futures]
         return results
 
-    async def run_batch_async(self, tasks_images: List[Tuple[str, str]]) -> List[str]:
+    async def run_batch_async(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
         """Process a batch of tasks and images asynchronously"""
         loop = asyncio.get_event_loop()
         futures = [
@@ -210,7 +227,9 @@ class GPT4Vision:
         """Process a batch of tasks and images asynchronously with retries"""
         loop = asyncio.get_event_loop()
         futures = [
-            loop.run_in_executor(None, self.run_with_retries, task, img)
+            loop.run_in_executor(
+                None, self.run_with_retries, task, img
+            )
             for task, img in tasks_images
         ]
         return await asyncio.gather(*futures)
@@ -237,7 +256,9 @@ class GPT4Vision:
     def health_check(self):
         """Health check for the GPT4Vision model"""
         try:
-            response = requests.get("https://api.openai.com/v1/engines")
+            response = requests.get(
+                "https://api.openai.com/v1/engines"
+            )
             return response.status_code == 200
         except requests.RequestException as error:
             print(f"Health check failed: {error}")
diff --git a/swarms/models/huggingface.py b/swarms/models/huggingface.py
index 0f226740..88620654 100644
--- a/swarms/models/huggingface.py
+++ b/swarms/models/huggingface.py
@@ -7,7 +7,11 @@ from typing import List, Tuple
 import torch
 from termcolor import colored
 from torch.nn.parallel import DistributedDataParallel as DDP
-from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
+from transformers import (
+    AutoModelForCausalLM,
+    AutoTokenizer,
+    BitsAndBytesConfig,
+)
 
 
 class HuggingfaceLLM:
@@ -133,7 +137,9 @@ class HuggingfaceLLM:
     ):
         self.logger = logging.getLogger(__name__)
         self.device = (
-            device if device else ("cuda" if torch.cuda.is_available() else "cpu")
+            device
+            if device
+            else ("cuda" if torch.cuda.is_available() else "cpu")
         )
         self.model_id = model_id
         self.max_length = max_length
@@ -171,14 +177,25 @@ class HuggingfaceLLM:
                 self.model_id, *args, **kwargs
             )
             self.model = AutoModelForCausalLM.from_pretrained(
-                self.model_id, quantization_config=bnb_config, *args, **kwargs
+                self.model_id,
+                quantization_config=bnb_config,
+                *args,
+                **kwargs,
             )
 
             self.model  # .to(self.device)
         except Exception as e:
             # self.logger.error(f"Failed to load the model or the tokenizer: {e}")
             # raise
-            print(colored(f"Failed to load the model and or the tokenizer: {e}", "red"))
+            print(
+                colored(
+                    (
+                        "Failed to load the model and or the"
+                        f" tokenizer: {e}"
+                    ),
+                    "red",
+                )
+            )
 
     def print_error(self, error: str):
         """Print error"""
@@ -192,7 +209,9 @@ class HuggingfaceLLM:
         """Load the model"""
         if not self.model or not self.tokenizer:
             try:
-                self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
+                self.tokenizer = AutoTokenizer.from_pretrained(
+                    self.model_id
+                )
 
                 bnb_config = (
                     BitsAndBytesConfig(**self.quantization_config)
@@ -207,20 +226,28 @@ class HuggingfaceLLM:
                 if self.distributed:
                     self.model = DDP(self.model)
             except Exception as error:
-                self.logger.error(f"Failed to load the model or the tokenizer: {error}")
+                self.logger.error(
+                    "Failed to load the model or the tokenizer:"
+                    f" {error}"
+                )
                 raise
 
     def concurrent_run(self, tasks: List[str], max_workers: int = 5):
         """Concurrently generate text for a list of prompts."""
-        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
+        with concurrent.futures.ThreadPoolExecutor(
+            max_workers=max_workers
+        ) as executor:
             results = list(executor.map(self.run, tasks))
         return results
 
-    def run_batch(self, tasks_images: List[Tuple[str, str]]) -> List[str]:
+    def run_batch(
+        self, tasks_images: List[Tuple[str, str]]
+    ) -> List[str]:
         """Process a batch of tasks and images"""
         with concurrent.futures.ThreadPoolExecutor() as executor:
             futures = [
-                executor.submit(self.run, task, img) for task, img in tasks_images
+                executor.submit(self.run, task, img)
+                for task, img in tasks_images
             ]
             results = [future.result() for future in futures]
         return results
@@ -243,7 +270,9 @@ class HuggingfaceLLM:
         self.print_dashboard(task)
 
         try:
-            inputs = self.tokenizer.encode(task, return_tensors="pt").to(self.device)
+            inputs = self.tokenizer.encode(
+                task, return_tensors="pt"
+            )
 
             # self.log.start()
 
@@ -253,7 +282,9 @@ class HuggingfaceLLM:
                         output_sequence = []
 
                         outputs = self.model.generate(
-                            inputs, max_length=len(inputs) + 1, do_sample=True
+                            inputs,
+                            max_length=len(inputs) + 1,
+                            do_sample=True,
                         )
                         output_tokens = outputs[0][-1]
                         output_sequence.append(output_tokens.item())
@@ -261,7 +292,8 @@ class HuggingfaceLLM:
                         # print token in real-time
                         print(
                             self.tokenizer.decode(
-                                [output_tokens], skip_special_tokens=True
+                                [output_tokens],
+                                skip_special_tokens=True,
                             ),
                             end="",
                             flush=True,
@@ -274,13 +306,16 @@ class HuggingfaceLLM:
                     )
 
             del inputs
-            return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return self.tokenizer.decode(
+                outputs[0], skip_special_tokens=True
+            )
         except Exception as e:
             print(
                 colored(
                     (
-                        f"HuggingfaceLLM could not generate text because of error: {e},"
-                        " try optimizing your arguments"
+                        "HuggingfaceLLM could not generate text"
+                        f" because of error: {e}, try optimizing your"
+                        " arguments"
                     ),
                     "red",
                 )
@@ -305,7 +340,9 @@ class HuggingfaceLLM:
         self.print_dashboard(task)
 
         try:
-            inputs = self.tokenizer.encode(task, return_tensors="pt").to(self.device)
+            inputs = self.tokenizer.encode(
+                task, return_tensors="pt"
+            ).to(self.device)
 
             # self.log.start()
 
@@ -315,7 +352,9 @@ class HuggingfaceLLM:
                         output_sequence = []
 
                         outputs = self.model.generate(
-                            inputs, max_length=len(inputs) + 1, do_sample=True
+                            inputs,
+                            max_length=len(inputs) + 1,
+                            do_sample=True,
                         )
                         output_tokens = outputs[0][-1]
                         output_sequence.append(output_tokens.item())
@@ -323,7 +362,8 @@ class HuggingfaceLLM:
                         # print token in real-time
                         print(
                             self.tokenizer.decode(
-                                [output_tokens], skip_special_tokens=True
+                                [output_tokens],
+                                skip_special_tokens=True,
                             ),
                             end="",
                             flush=True,
@@ -337,7 +377,9 @@ class HuggingfaceLLM:
 
             del inputs
 
-            return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return self.tokenizer.decode(
+                outputs[0], skip_special_tokens=True
+            )
         except Exception as e:
             self.logger.error(f"Failed to generate the text: {e}")
             raise
@@ -409,7 +451,8 @@ class HuggingfaceLLM:
                 The new device to use for inference.
         """
         self.device = device
-        self.model.to(self.device)
+        if self.model is not None:
+            self.model.to(self.device)
 
     def set_max_length(self, max_length):
         """Set max_length"""
diff --git a/swarms/models/idefics.py b/swarms/models/idefics.py
index 73cb4991..7c505d8a 100644
--- a/swarms/models/idefics.py
+++ b/swarms/models/idefics.py
@@ -66,7 +66,9 @@ class Idefics:
         max_length=100,
     ):
         self.device = (
-            device if device else ("cuda" if torch.cuda.is_available() else "cpu")
+            device
+            if device
+            else ("cuda" if torch.cuda.is_available() else "cpu")
         )
         self.model = IdeficsForVisionText2Text.from_pretrained(
             checkpoint,
@@ -98,10 +100,14 @@ class Idefics:
         """
         inputs = (
             self.processor(
-                prompts, add_end_of_utterance_token=False, return_tensors="pt"
+                prompts,
+                add_end_of_utterance_token=False,
+                return_tensors="pt",
             ).to(self.device)
             if batched_mode
-            else self.processor(prompts[0], return_tensors="pt").to(self.device)
+            else self.processor(prompts[0], return_tensors="pt").to(
+                self.device
+            )
         )
 
         exit_condition = self.processor.tokenizer(
@@ -109,7 +115,8 @@ class Idefics:
         ).input_ids
 
         bad_words_ids = self.processor.tokenizer(
-            ["<image>", "<fake_token_around_image"], add_special_tokens=False
+            ["<image>", "<fake_token_around_image"],
+            add_special_tokens=False,
         ).input_ids
 
         generated_ids = self.model.generate(
@@ -143,10 +150,14 @@ class Idefics:
         """
         inputs = (
             self.processor(
-                prompts, add_end_of_utterance_token=False, return_tensors="pt"
+                prompts,
+                add_end_of_utterance_token=False,
+                return_tensors="pt",
             ).to(self.device)
             if batched_mode
-            else self.processor(prompts[0], return_tensors="pt").to(self.device)
+            else self.processor(prompts[0], return_tensors="pt").to(
+                self.device
+            )
         )
 
         exit_condition = self.processor.tokenizer(
@@ -154,7 +165,8 @@ class Idefics:
         ).input_ids
 
         bad_words_ids = self.processor.tokenizer(
-            ["<image>", "<fake_token_around_image"], add_special_tokens=False
+            ["<image>", "<fake_token_around_image"],
+            add_special_tokens=False,
         ).input_ids
 
         generated_ids = self.model.generate(
diff --git a/swarms/models/jina_embeds.py b/swarms/models/jina_embeds.py
index a72b8a9e..c294f764 100644
--- a/swarms/models/jina_embeds.py
+++ b/swarms/models/jina_embeds.py
@@ -3,7 +3,11 @@ import logging
 import torch
 from numpy.linalg import norm
 from torch.nn.parallel import DistributedDataParallel as DDP
-from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
+from transformers import (
+    AutoModelForCausalLM,
+    AutoTokenizer,
+    BitsAndBytesConfig,
+)
 
 
 def cos_sim(a, b):
@@ -54,7 +58,9 @@ class JinaEmbeddings:
     ):
         self.logger = logging.getLogger(__name__)
         self.device = (
-            device if device else ("cuda" if torch.cuda.is_available() else "cpu")
+            device
+            if device
+            else ("cuda" if torch.cuda.is_available() else "cpu")
         )
         self.model_id = model_id
         self.max_length = max_length
@@ -83,19 +89,25 @@ class JinaEmbeddings:
 
         try:
             self.model = AutoModelForCausalLM.from_pretrained(
-                self.model_id, quantization_config=bnb_config, trust_remote_code=True
+                self.model_id,
+                quantization_config=bnb_config,
+                trust_remote_code=True,
             )
 
             self.model  # .to(self.device)
         except Exception as e:
-            self.logger.error(f"Failed to load the model or the tokenizer: {e}")
+            self.logger.error(
+                f"Failed to load the model or the tokenizer: {e}"
+            )
             raise
 
     def load_model(self):
         """Load the model"""
         if not self.model or not self.tokenizer:
             try:
-                self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
+                self.tokenizer = AutoTokenizer.from_pretrained(
+                    self.model_id
+                )
 
                 bnb_config = (
                     BitsAndBytesConfig(**self.quantization_config)
@@ -112,7 +124,10 @@ class JinaEmbeddings:
                 if self.distributed:
                     self.model = DDP(self.model)
             except Exception as error:
-                self.logger.error(f"Failed to load the model or the tokenizer: {error}")
+                self.logger.error(
+                    "Failed to load the model or the tokenizer:"
+                    f" {error}"
+                )
                 raise
 
     def run(self, task: str):
@@ -131,7 +146,9 @@ class JinaEmbeddings:
         max_length = self.max_length
 
         try:
-            embeddings = self.model.encode([task], max_length=max_length)
+            embeddings = self.model.encode(
+                [task], max_length=max_length
+            )
 
             if self.cos_sim:
                 print(cos_sim(embeddings[0], embeddings[1]))
@@ -180,7 +197,9 @@ class JinaEmbeddings:
         max_length = self.max_length
 
         try:
-            embeddings = self.model.encode([task], max_length=max_length)
+            embeddings = self.model.encode(
+                [task], max_length=max_length
+            )
 
             if self.cos_sim:
                 print(cos_sim(embeddings[0], embeddings[1]))
diff --git a/swarms/models/kosmos2.py b/swarms/models/kosmos2.py
index b0e1a9f6..9a9a0de3 100644
--- a/swarms/models/kosmos2.py
+++ b/swarms/models/kosmos2.py
@@ -20,7 +20,9 @@ class Detections(BaseModel):
         ), "All fields must have the same length."
         return values
 
-    @validator("xyxy", "class_id", "confidence", pre=True, each_item=True)
+    @validator(
+        "xyxy", "class_id", "confidence", pre=True, each_item=True
+    )
     def check_not_empty(cls, v):
         if isinstance(v, list) and len(v) == 0:
             raise ValueError("List must not be empty")
@@ -69,19 +71,25 @@ class Kosmos2(BaseModel):
         image = Image.open(img)
         prompt = "<grounding>An image of"
 
-        inputs = self.processor(text=prompt, images=image, return_tensors="pt")
-        outputs = self.model.generate(**inputs, use_cache=True, max_new_tokens=64)
+        inputs = self.processor(
+            text=prompt, images=image, return_tensors="pt"
+        )
+        outputs = self.model.generate(
+            **inputs, use_cache=True, max_new_tokens=64
+        )
 
-        generated_text = self.processor.batch_decode(outputs, skip_special_tokens=True)[
-            0
-        ]
+        generated_text = self.processor.batch_decode(
+            outputs, skip_special_tokens=True
+        )[0]
 
         # The actual processing of generated_text to entities would go here
         # For the purpose of this example, assume a mock function 'extract_entities' exists:
         entities = self.extract_entities(generated_text)
 
         # Convert entities to detections format
-        detections = self.process_entities_to_detections(entities, image)
+        detections = self.process_entities_to_detections(
+            entities, image
+        )
         return detections
 
     def extract_entities(
@@ -99,7 +107,9 @@ class Kosmos2(BaseModel):
         if not entities:
             return Detections.empty()
 
-        class_ids = [0] * len(entities)  # Replace with actual class ID extraction logic
+        class_ids = [0] * len(
+            entities
+        )  # Replace with actual class ID extraction logic
         xyxys = [
             (
                 e[1][0] * image.width,
@@ -111,7 +121,9 @@ class Kosmos2(BaseModel):
         ]
         confidences = [1.0] * len(entities)  # Placeholder confidence
 
-        return Detections(xyxy=xyxys, class_id=class_ids, confidence=confidences)
+        return Detections(
+            xyxy=xyxys, class_id=class_ids, confidence=confidences
+        )
 
 
 # Usage:
diff --git a/swarms/models/kosmos_two.py b/swarms/models/kosmos_two.py
index 596886f3..3b1d4233 100644
--- a/swarms/models/kosmos_two.py
+++ b/swarms/models/kosmos_two.py
@@ -18,38 +18,31 @@ def is_overlapping(rect1, rect2):
 
 class Kosmos:
     """
+    Kosmos model by Yen-Chun Shieh
 
-    Args:
+    Parameters
+    ----------
+    model_name : str
+        Path to the pretrained model
 
+    Examples
+    --------
+    >>> kosmos = Kosmos()
+    >>> kosmos("Hello, my name is", "path/to/image.png")
 
-    # Initialize Kosmos
-    kosmos = Kosmos()
-
-    # Perform multimodal grounding
-    kosmos.multimodal_grounding("Find the red apple in the image.", "https://example.com/apple.jpg")
-
-    # Perform referring expression comprehension
-    kosmos.referring_expression_comprehension("Show me the green bottle.", "https://example.com/bottle.jpg")
-
-    # Generate referring expressions
-    kosmos.referring_expression_generation("It is on the table.", "https://example.com/table.jpg")
-
-    # Perform grounded visual question answering
-    kosmos.grounded_vqa("What is the color of the car?", "https://example.com/car.jpg")
-
-    # Generate grounded image caption
-    kosmos.grounded_image_captioning("https://example.com/beach.jpg")
     """
 
     def __init__(
         self,
         model_name="ydshieh/kosmos-2-patch14-224",
+        *args,
+        **kwargs,
     ):
         self.model = AutoModelForVision2Seq.from_pretrained(
-            model_name, trust_remote_code=True
+            model_name, trust_remote_code=True, *args, **kwargs
         )
         self.processor = AutoProcessor.from_pretrained(
-            model_name, trust_remote_code=True
+            model_name, trust_remote_code=True, *args, **kwargs
         )
 
     def get_image(self, url):
@@ -58,7 +51,9 @@ class Kosmos:
 
     def run(self, prompt, image):
         """Run Kosmos"""
-        inputs = self.processor(text=prompt, images=image, return_tensors="pt")
+        inputs = self.processor(
+            text=prompt, images=image, return_tensors="pt"
+        )
         generated_ids = self.model.generate(
             pixel_values=inputs["pixel_values"],
             input_ids=inputs["input_ids"][:, :-1],
@@ -72,13 +67,15 @@ class Kosmos:
             generated_ids,
             skip_special_tokens=True,
         )[0]
-        processed_text, entities = self.processor.post_process_generation(
-            generated_texts
+        processed_text, entities = (
+            self.processor.post_process_generation(generated_texts)
         )
 
     def __call__(self, prompt, image):
         """Run call"""
-        inputs = self.processor(text=prompt, images=image, return_tensors="pt")
+        inputs = self.processor(
+            text=prompt, images=image, return_tensors="pt"
+        )
         generated_ids = self.model.generate(
             pixel_values=inputs["pixel_values"],
             input_ids=inputs["input_ids"][:, :-1],
@@ -92,8 +89,8 @@ class Kosmos:
             generated_ids,
             skip_special_tokens=True,
         )[0]
-        processed_text, entities = self.processor.post_process_generation(
-            generated_texts
+        processed_text, entities = (
+            self.processor.post_process_generation(generated_texts)
         )
 
     # tasks
@@ -124,7 +121,9 @@ class Kosmos:
         prompt = "<grounding> Describe this image in detail"
         self.run(prompt, image_url)
 
-    def draw_entity_boxes_on_image(image, entities, show=False, save_path=None):
+    def draw_entity_boxes_on_image(
+        image, entities, show=False, save_path=None
+    ):
         """_summary_
         Args:
             image (_type_): image or image path
@@ -145,19 +144,23 @@ class Kosmos:
         elif isinstance(image, torch.Tensor):
             # pdb.set_trace()
             image_tensor = image.cpu()
-            reverse_norm_mean = torch.tensor([0.48145466, 0.4578275, 0.40821073])[
-                :, None, None
-            ]
-            reverse_norm_std = torch.tensor([0.26862954, 0.26130258, 0.27577711])[
-                :, None, None
-            ]
-            image_tensor = image_tensor * reverse_norm_std + reverse_norm_mean
+            reverse_norm_mean = torch.tensor(
+                [0.48145466, 0.4578275, 0.40821073]
+            )[:, None, None]
+            reverse_norm_std = torch.tensor(
+                [0.26862954, 0.26130258, 0.27577711]
+            )[:, None, None]
+            image_tensor = (
+                image_tensor * reverse_norm_std + reverse_norm_mean
+            )
             pil_img = T.ToPILImage()(image_tensor)
             image_h = pil_img.height
             image_w = pil_img.width
             image = np.array(pil_img)[:, :, [2, 1, 0]]
         else:
-            raise ValueError(f"invaild image format, {type(image)} for {image}")
+            raise ValueError(
+                f"invaild image format, {type(image)} for {image}"
+            )
 
         if len(entities) == 0:
             return image
@@ -186,9 +189,15 @@ class Kosmos:
                 )
                 # draw bbox
                 # random color
-                color = tuple(np.random.randint(0, 255, size=3).tolist())
+                color = tuple(
+                    np.random.randint(0, 255, size=3).tolist()
+                )
                 new_image = cv2.rectangle(
-                    new_image, (orig_x1, orig_y1), (orig_x2, orig_y2), color, box_line
+                    new_image,
+                    (orig_x1, orig_y1),
+                    (orig_x2, orig_y2),
+                    color,
+                    box_line,
                 )
 
                 l_o, r_o = (
@@ -199,7 +208,12 @@ class Kosmos:
                 x1 = orig_x1 - l_o
                 y1 = orig_y1 - l_o
 
-                if y1 < text_height + text_offset_original + 2 * text_spaces:
+                if (
+                    y1
+                    < text_height
+                    + text_offset_original
+                    + 2 * text_spaces
+                ):
                     y1 = (
                         orig_y1
                         + r_o
@@ -211,33 +225,57 @@ class Kosmos:
 
                 # add text background
                 (text_width, text_height), _ = cv2.getTextSize(
-                    f"  {entity_name}", cv2.FONT_HERSHEY_COMPLEX, text_size, text_line
+                    f"  {entity_name}",
+                    cv2.FONT_HERSHEY_COMPLEX,
+                    text_size,
+                    text_line,
                 )
                 text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2 = (
                     x1,
-                    y1 - (text_height + text_offset_original + 2 * text_spaces),
+                    y1
+                    - (
+                        text_height
+                        + text_offset_original
+                        + 2 * text_spaces
+                    ),
                     x1 + text_width,
                     y1,
                 )
 
                 for prev_bbox in previous_bboxes:
                     while is_overlapping(
-                        (text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2), prev_bbox
+                        (
+                            text_bg_x1,
+                            text_bg_y1,
+                            text_bg_x2,
+                            text_bg_y2,
+                        ),
+                        prev_bbox,
                     ):
                         text_bg_y1 += (
-                            text_height + text_offset_original + 2 * text_spaces
+                            text_height
+                            + text_offset_original
+                            + 2 * text_spaces
                         )
                         text_bg_y2 += (
-                            text_height + text_offset_original + 2 * text_spaces
+                            text_height
+                            + text_offset_original
+                            + 2 * text_spaces
+                        )
+                        y1 += (
+                            text_height
+                            + text_offset_original
+                            + 2 * text_spaces
                         )
-                        y1 += text_height + text_offset_original + 2 * text_spaces
 
                         if text_bg_y2 >= image_h:
                             text_bg_y1 = max(
                                 0,
                                 image_h
                                 - (
-                                    text_height + text_offset_original + 2 * text_spaces
+                                    text_height
+                                    + text_offset_original
+                                    + 2 * text_spaces
                                 ),
                             )
                             text_bg_y2 = image_h
@@ -270,7 +308,9 @@ class Kosmos:
                     cv2.LINE_AA,
                 )
                 # previous_locations.append((x1, y1))
-                previous_bboxes.append((text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2))
+                previous_bboxes.append(
+                    (text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2)
+                )
 
         pil_image = Image.fromarray(new_image[:, :, [2, 1, 0]])
         if save_path:
diff --git a/swarms/models/llama_function_caller.py b/swarms/models/llama_function_caller.py
index a991641a..78169208 100644
--- a/swarms/models/llama_function_caller.py
+++ b/swarms/models/llama_function_caller.py
@@ -121,7 +121,11 @@ class LlamaFunctionCaller:
         )
 
     def add_func(
-        self, name: str, function: Callable, description: str, arguments: List[Dict]
+        self,
+        name: str,
+        function: Callable,
+        description: str,
+        arguments: List[Dict],
     ):
         """
         Adds a new function to the LlamaFunctionCaller.
@@ -166,18 +170,25 @@ class LlamaFunctionCaller:
         prompt = f"{task}\n\n"
 
         # Encode and send to the model
-        inputs = self.tokenizer([prompt], return_tensors="pt").to(self.runtime)
+        inputs = self.tokenizer([prompt], return_tensors="pt").to(
+            self.runtime
+        )
 
         streamer = TextStreamer(self.tokenizer)
 
         if self.streaming:
             out = self.model.generate(
-                **inputs, streamer=streamer, max_new_tokens=self.max_tokens, **kwargs
+                **inputs,
+                streamer=streamer,
+                max_new_tokens=self.max_tokens,
+                **kwargs,
             )
 
             return out
         else:
-            out = self.model.generate(**inputs, max_length=self.max_tokens, **kwargs)
+            out = self.model.generate(
+                **inputs, max_length=self.max_tokens, **kwargs
+            )
             # return self.tokenizer.decode(out[0], skip_special_tokens=True)
             return out
 
diff --git a/swarms/models/llava.py b/swarms/models/llava.py
index 6f8019bc..605904c3 100644
--- a/swarms/models/llava.py
+++ b/swarms/models/llava.py
@@ -70,7 +70,10 @@ class MultiModalLlava:
 
     def chat(self):
         """Interactive chat in terminal"""
-        print("Starting chat with LlavaModel. Type 'exit' to end the session.")
+        print(
+            "Starting chat with LlavaModel. Type 'exit' to end the"
+            " session."
+        )
         while True:
             user_input = input("You: ")
             if user_input.lower() == "exit":
diff --git a/swarms/models/mistral.py b/swarms/models/mistral.py
index 7f48a0d6..297ecf12 100644
--- a/swarms/models/mistral.py
+++ b/swarms/models/mistral.py
@@ -49,7 +49,10 @@ class Mistral:
 
         # Check if the specified device is available
         if not torch.cuda.is_available() and device == "cuda":
-            raise ValueError("CUDA is not available. Please choose a different device.")
+            raise ValueError(
+                "CUDA is not available. Please choose a different"
+                " device."
+            )
 
         # Load the model and tokenizer
         self.model = None
@@ -60,17 +63,25 @@ class Mistral:
 
     def load_model(self):
         try:
-            self.model = AutoModelForCausalLM.from_pretrained(self.model_name)
-            self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
+            self.model = AutoModelForCausalLM.from_pretrained(
+                self.model_name
+            )
+            self.tokenizer = AutoTokenizer.from_pretrained(
+                self.model_name
+            )
             self.model.to(self.device)
         except Exception as e:
-            raise ValueError(f"Error loading the Mistral model: {str(e)}")
+            raise ValueError(
+                f"Error loading the Mistral model: {str(e)}"
+            )
 
     def run(self, task: str):
         """Run the model on a given task."""
 
         try:
-            model_inputs = self.tokenizer([task], return_tensors="pt").to(self.device)
+            model_inputs = self.tokenizer(
+                [task], return_tensors="pt"
+            ).to(self.device)
             generated_ids = self.model.generate(
                 **model_inputs,
                 max_length=self.max_length,
@@ -78,7 +89,9 @@ class Mistral:
                 temperature=self.temperature,
                 max_new_tokens=self.max_length,
             )
-            output_text = self.tokenizer.batch_decode(generated_ids)[0]
+            output_text = self.tokenizer.batch_decode(generated_ids)[
+                0
+            ]
             return output_text
         except Exception as e:
             raise ValueError(f"Error running the model: {str(e)}")
@@ -87,7 +100,9 @@ class Mistral:
         """Run the model on a given task."""
 
         try:
-            model_inputs = self.tokenizer([task], return_tensors="pt").to(self.device)
+            model_inputs = self.tokenizer(
+                [task], return_tensors="pt"
+            ).to(self.device)
             generated_ids = self.model.generate(
                 **model_inputs,
                 max_length=self.max_length,
@@ -95,7 +110,9 @@ class Mistral:
                 temperature=self.temperature,
                 max_new_tokens=self.max_length,
             )
-            output_text = self.tokenizer.batch_decode(generated_ids)[0]
+            output_text = self.tokenizer.batch_decode(generated_ids)[
+                0
+            ]
             return output_text
         except Exception as e:
             raise ValueError(f"Error running the model: {str(e)}")
diff --git a/swarms/models/mpt.py b/swarms/models/mpt.py
index 46d1a357..56f1bbdb 100644
--- a/swarms/models/mpt.py
+++ b/swarms/models/mpt.py
@@ -29,7 +29,12 @@ class MPT7B:
 
     """
 
-    def __init__(self, model_name: str, tokenizer_name: str, max_tokens: int = 100):
+    def __init__(
+        self,
+        model_name: str,
+        tokenizer_name: str,
+        max_tokens: int = 100,
+    ):
         # Loading model and tokenizer details
         self.model_name = model_name
         self.tokenizer_name = tokenizer_name
@@ -118,7 +123,10 @@ class MPT7B:
         """
         with torch.autocast("cuda", dtype=torch.bfloat16):
             return self.pipe(
-                prompt, max_new_tokens=self.max_tokens, do_sample=True, use_cache=True
+                prompt,
+                max_new_tokens=self.max_tokens,
+                do_sample=True,
+                use_cache=True,
             )[0]["generated_text"]
 
     async def generate_async(self, prompt: str) -> str:
@@ -133,9 +141,13 @@ class MPT7B:
         """Call the model asynchronously""" ""
         return await self.run_async(task, *args, **kwargs)
 
-    def batch_generate(self, prompts: list, temperature: float = 1.0) -> list:
+    def batch_generate(
+        self, prompts: list, temperature: float = 1.0
+    ) -> list:
         """Batch generate text"""
-        self.logger.info(f"Generating text for {len(prompts)} prompts...")
+        self.logger.info(
+            f"Generating text for {len(prompts)} prompts..."
+        )
         results = []
         with torch.autocast("cuda", dtype=torch.bfloat16):
             for prompt in prompts:
diff --git a/swarms/models/nougat.py b/swarms/models/nougat.py
index f156981c..453c6cae 100644
--- a/swarms/models/nougat.py
+++ b/swarms/models/nougat.py
@@ -18,7 +18,7 @@ class Nougat:
     """
     Nougat
 
-    ArgsS:
+    Args:
         model_name_or_path: str, default="facebook/nougat-base"
         min_length: int, default=1
         max_new_tokens: int, default=30
@@ -35,26 +35,35 @@ class Nougat:
         self,
         model_name_or_path="facebook/nougat-base",
         min_length: int = 1,
-        max_new_tokens: int = 30,
+        max_new_tokens: int = 5000,
     ):
         self.model_name_or_path = model_name_or_path
         self.min_length = min_length
         self.max_new_tokens = max_new_tokens
 
-        self.processor = NougatProcessor.from_pretrained(self.model_name_or_path)
-        self.model = VisionEncoderDecoderModel.from_pretrained(self.model_name_or_path)
+        self.processor = NougatProcessor.from_pretrained(
+            self.model_name_or_path
+        )
+        self.model = VisionEncoderDecoderModel.from_pretrained(
+            self.model_name_or_path
+        )
         self.device = "cuda" if torch.cuda.is_available() else "cpu"
         self.model.to(self.device)
 
-    def get_image(self, img_path: str):
+    def get_image(self, img: str):
         """Get an image from a path"""
-        image = Image.open(img_path)
-        return image
+        img = Image.open(img)
 
-    def __call__(self, img_path: str):
+        if img.mode == "L":
+            img = img.convert("RGB")
+        return img
+
+    def __call__(self, img: str):
         """Call the model with an image_path str as an input"""
-        image = Image.open(img_path)
-        pixel_values = self.processor(image, return_tensors="pt").pixel_values
+        image = Image.open(img)
+        pixel_values = self.processor(
+            image, return_tensors="pt"
+        ).pixel_values
 
         # Generate transcriptions, here we only generate 30 tokens
         outputs = self.model.generate(
@@ -63,13 +72,18 @@ class Nougat:
             max_new_tokens=self.max_new_tokens,
         )
 
-        sequence = self.processor.batch_decode(outputs, skip_special_tokens=True)[0]
-        sequence = self.processor.post_process_generation(sequence, fix_markdown=False)
+        sequence = self.processor.batch_decode(
+            outputs, skip_special_tokens=True
+        )[0]
+        sequence = self.processor.post_process_generation(
+            sequence, fix_markdown=False
+        )
 
         out = print(sequence)
         return out
 
     def clean_nougat_output(raw_output):
+        """Clean the output from nougat to be more readable"""
         # Define the pattern to extract the relevant data
         daily_balance_pattern = (
             r"\*\*(\d{2}/\d{2}/\d{4})\*\*\n\n\*\*([\d,]+\.\d{2})\*\*"
@@ -80,7 +94,9 @@ class Nougat:
 
         # Convert the matches to a readable format
         cleaned_data = [
-            "Date: {}, Amount: {}".format(date, amount.replace(",", ""))
+            "Date: {}, Amount: {}".format(
+                date, amount.replace(",", "")
+            )
             for date, amount in matches
         ]
 
diff --git a/swarms/models/openai_embeddings.py b/swarms/models/openai_embeddings.py
index 81dea550..0cbbdbee 100644
--- a/swarms/models/openai_embeddings.py
+++ b/swarms/models/openai_embeddings.py
@@ -43,7 +43,9 @@ def get_pydantic_field_names(cls: Any) -> Set[str]:
 logger = logging.getLogger(__name__)
 
 
-def _create_retry_decorator(embeddings: OpenAIEmbeddings) -> Callable[[Any], Any]:
+def _create_retry_decorator(
+    embeddings: OpenAIEmbeddings,
+) -> Callable[[Any], Any]:
     import llm
 
     min_seconds = 4
@@ -53,13 +55,17 @@ def _create_retry_decorator(embeddings: OpenAIEmbeddings) -> Callable[[Any], Any
     return retry(
         reraise=True,
         stop=stop_after_attempt(embeddings.max_retries),
-        wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
+        wait=wait_exponential(
+            multiplier=1, min=min_seconds, max=max_seconds
+        ),
         retry=(
             retry_if_exception_type(llm.error.Timeout)
             | retry_if_exception_type(llm.error.APIError)
             | retry_if_exception_type(llm.error.APIConnectionError)
             | retry_if_exception_type(llm.error.RateLimitError)
-            | retry_if_exception_type(llm.error.ServiceUnavailableError)
+            | retry_if_exception_type(
+                llm.error.ServiceUnavailableError
+            )
         ),
         before_sleep=before_sleep_log(logger, logging.WARNING),
     )
@@ -75,13 +81,17 @@ def _async_retry_decorator(embeddings: OpenAIEmbeddings) -> Any:
     async_retrying = AsyncRetrying(
         reraise=True,
         stop=stop_after_attempt(embeddings.max_retries),
-        wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
+        wait=wait_exponential(
+            multiplier=1, min=min_seconds, max=max_seconds
+        ),
         retry=(
             retry_if_exception_type(llm.error.Timeout)
             | retry_if_exception_type(llm.error.APIError)
             | retry_if_exception_type(llm.error.APIConnectionError)
             | retry_if_exception_type(llm.error.RateLimitError)
-            | retry_if_exception_type(llm.error.ServiceUnavailableError)
+            | retry_if_exception_type(
+                llm.error.ServiceUnavailableError
+            )
         ),
         before_sleep=before_sleep_log(logger, logging.WARNING),
     )
@@ -102,11 +112,15 @@ def _check_response(response: dict) -> dict:
     if any(len(d["embedding"]) == 1 for d in response["data"]):
         import llm
 
-        raise llm.error.APIError("OpenAI API returned an empty embedding")
+        raise llm.error.APIError(
+            "OpenAI API returned an empty embedding"
+        )
     return response
 
 
-def embed_with_retry(embeddings: OpenAIEmbeddings, **kwargs: Any) -> Any:
+def embed_with_retry(
+    embeddings: OpenAIEmbeddings, **kwargs: Any
+) -> Any:
     """Use tenacity to retry the embedding call."""
     retry_decorator = _create_retry_decorator(embeddings)
 
@@ -118,7 +132,9 @@ def embed_with_retry(embeddings: OpenAIEmbeddings, **kwargs: Any) -> Any:
     return _embed_with_retry(**kwargs)
 
 
-async def async_embed_with_retry(embeddings: OpenAIEmbeddings, **kwargs: Any) -> Any:
+async def async_embed_with_retry(
+    embeddings: OpenAIEmbeddings, **kwargs: Any
+) -> Any:
     """Use tenacity to retry the embedding call."""
 
     @_async_retry_decorator(embeddings)
@@ -185,12 +201,16 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
     openai_api_key: Optional[str] = None
     openai_organization: Optional[str] = None
     allowed_special: Union[Literal["all"], Set[str]] = set()
-    disallowed_special: Union[Literal["all"], Set[str], Sequence[str]] = "all"
+    disallowed_special: Union[
+        Literal["all"], Set[str], Sequence[str]
+    ] = "all"
     chunk_size: int = 1000
     """Maximum number of texts to embed in each batch"""
     max_retries: int = 6
     """Maximum number of retries to make when generating."""
-    request_timeout: Optional[Union[float, Tuple[float, float]]] = None
+    request_timeout: Optional[Union[float, Tuple[float, float]]] = (
+        None
+    )
     """Timeout in seconds for the OpenAPI request."""
     headers: Any = None
     tiktoken_model_name: Optional[str] = None
@@ -220,7 +240,9 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
         extra = values.get("model_kwargs", {})
         for field_name in list(values):
             if field_name in extra:
-                raise ValueError(f"Found {field_name} supplied twice.")
+                raise ValueError(
+                    f"Found {field_name} supplied twice."
+                )
             if field_name not in all_required_field_names:
                 warnings.warn(
                     f"""WARNING! {field_name} is not default parameter.
@@ -229,11 +251,14 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                 )
                 extra[field_name] = values.pop(field_name)
 
-        invalid_model_kwargs = all_required_field_names.intersection(extra.keys())
+        invalid_model_kwargs = all_required_field_names.intersection(
+            extra.keys()
+        )
         if invalid_model_kwargs:
             raise ValueError(
-                f"Parameters {invalid_model_kwargs} should be specified explicitly. "
-                "Instead they were passed in as part of `model_kwargs` parameter."
+                f"Parameters {invalid_model_kwargs} should be"
+                " specified explicitly. Instead they were passed in"
+                " as part of `model_kwargs` parameter."
             )
 
         values["model_kwargs"] = extra
@@ -263,7 +288,11 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
             "OPENAI_PROXY",
             default="",
         )
-        if values["openai_api_type"] in ("azure", "azure_ad", "azuread"):
+        if values["openai_api_type"] in (
+            "azure",
+            "azure_ad",
+            "azuread",
+        ):
             default_api_version = "2022-12-01"
         else:
             default_api_version = ""
@@ -315,9 +344,15 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
         return openai_args
 
     def _get_len_safe_embeddings(
-        self, texts: List[str], *, engine: str, chunk_size: Optional[int] = None
+        self,
+        texts: List[str],
+        *,
+        engine: str,
+        chunk_size: Optional[int] = None,
     ) -> List[List[float]]:
-        embeddings: List[List[float]] = [[] for _ in range(len(texts))]
+        embeddings: List[List[float]] = [
+            [] for _ in range(len(texts))
+        ]
         try:
             import tiktoken
         except ImportError:
@@ -333,7 +368,10 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
         try:
             encoding = tiktoken.encoding_for_model(model_name)
         except KeyError:
-            logger.warning("Warning: model not found. Using cl100k_base encoding.")
+            logger.warning(
+                "Warning: model not found. Using cl100k_base"
+                " encoding."
+            )
             model = "cl100k_base"
             encoding = tiktoken.get_encoding(model)
         for i, text in enumerate(texts):
@@ -347,7 +385,9 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                 disallowed_special=self.disallowed_special,
             )
             for j in range(0, len(token), self.embedding_ctx_length):
-                tokens.append(token[j : j + self.embedding_ctx_length])
+                tokens.append(
+                    token[j : j + self.embedding_ctx_length]
+                )
                 indices.append(i)
 
         batched_embeddings: List[List[float]] = []
@@ -369,10 +409,16 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                 input=tokens[i : i + _chunk_size],
                 **self._invocation_params,
             )
-            batched_embeddings.extend(r["embedding"] for r in response["data"])
+            batched_embeddings.extend(
+                r["embedding"] for r in response["data"]
+            )
 
-        results: List[List[List[float]]] = [[] for _ in range(len(texts))]
-        num_tokens_in_batch: List[List[int]] = [[] for _ in range(len(texts))]
+        results: List[List[List[float]]] = [
+            [] for _ in range(len(texts))
+        ]
+        num_tokens_in_batch: List[List[int]] = [
+            [] for _ in range(len(texts))
+        ]
         for i in range(len(indices)):
             results[indices[i]].append(batched_embeddings[i])
             num_tokens_in_batch[indices[i]].append(len(tokens[i]))
@@ -384,21 +430,29 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                     self,
                     input="",
                     **self._invocation_params,
-                )[
-                    "data"
-                ][0]["embedding"]
+                )["data"][0]["embedding"]
             else:
-                average = np.average(_result, axis=0, weights=num_tokens_in_batch[i])
-            embeddings[i] = (average / np.linalg.norm(average)).tolist()
+                average = np.average(
+                    _result, axis=0, weights=num_tokens_in_batch[i]
+                )
+            embeddings[i] = (
+                average / np.linalg.norm(average)
+            ).tolist()
 
         return embeddings
 
     # please refer to
     # https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_long_inputs.ipynb
     async def _aget_len_safe_embeddings(
-        self, texts: List[str], *, engine: str, chunk_size: Optional[int] = None
+        self,
+        texts: List[str],
+        *,
+        engine: str,
+        chunk_size: Optional[int] = None,
     ) -> List[List[float]]:
-        embeddings: List[List[float]] = [[] for _ in range(len(texts))]
+        embeddings: List[List[float]] = [
+            [] for _ in range(len(texts))
+        ]
         try:
             import tiktoken
         except ImportError:
@@ -414,7 +468,10 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
         try:
             encoding = tiktoken.encoding_for_model(model_name)
         except KeyError:
-            logger.warning("Warning: model not found. Using cl100k_base encoding.")
+            logger.warning(
+                "Warning: model not found. Using cl100k_base"
+                " encoding."
+            )
             model = "cl100k_base"
             encoding = tiktoken.get_encoding(model)
         for i, text in enumerate(texts):
@@ -428,7 +485,9 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                 disallowed_special=self.disallowed_special,
             )
             for j in range(0, len(token), self.embedding_ctx_length):
-                tokens.append(token[j : j + self.embedding_ctx_length])
+                tokens.append(
+                    token[j : j + self.embedding_ctx_length]
+                )
                 indices.append(i)
 
         batched_embeddings: List[List[float]] = []
@@ -439,10 +498,16 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                 input=tokens[i : i + _chunk_size],
                 **self._invocation_params,
             )
-            batched_embeddings.extend(r["embedding"] for r in response["data"])
+            batched_embeddings.extend(
+                r["embedding"] for r in response["data"]
+            )
 
-        results: List[List[List[float]]] = [[] for _ in range(len(texts))]
-        num_tokens_in_batch: List[List[int]] = [[] for _ in range(len(texts))]
+        results: List[List[List[float]]] = [
+            [] for _ in range(len(texts))
+        ]
+        num_tokens_in_batch: List[List[int]] = [
+            [] for _ in range(len(texts))
+        ]
         for i in range(len(indices)):
             results[indices[i]].append(batched_embeddings[i])
             num_tokens_in_batch[indices[i]].append(len(tokens[i]))
@@ -458,8 +523,12 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
                     )
                 )["data"][0]["embedding"]
             else:
-                average = np.average(_result, axis=0, weights=num_tokens_in_batch[i])
-            embeddings[i] = (average / np.linalg.norm(average)).tolist()
+                average = np.average(
+                    _result, axis=0, weights=num_tokens_in_batch[i]
+                )
+            embeddings[i] = (
+                average / np.linalg.norm(average)
+            ).tolist()
 
         return embeddings
 
@@ -478,7 +547,9 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
         """
         # NOTE: to keep things simple, we assume the list may contain texts longer
         #       than the maximum context and use length-safe embedding function.
-        return self._get_len_safe_embeddings(texts, engine=self.deployment)
+        return self._get_len_safe_embeddings(
+            texts, engine=self.deployment
+        )
 
     async def aembed_documents(
         self, texts: List[str], chunk_size: Optional[int] = 0
@@ -495,7 +566,9 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
         """
         # NOTE: to keep things simple, we assume the list may contain texts longer
         #       than the maximum context and use length-safe embedding function.
-        return await self._aget_len_safe_embeddings(texts, engine=self.deployment)
+        return await self._aget_len_safe_embeddings(
+            texts, engine=self.deployment
+        )
 
     def embed_query(self, text: str) -> List[float]:
         """Call out to OpenAI's embedding endpoint for embedding query text.
diff --git a/swarms/models/openai_function_caller.py b/swarms/models/openai_function_caller.py
index bac0f28d..6542e457 100644
--- a/swarms/models/openai_function_caller.py
+++ b/swarms/models/openai_function_caller.py
@@ -3,7 +3,11 @@ from typing import Any, Dict, List, Optional, Union
 import openai
 import requests
 from pydantic import BaseModel, validator
-from tenacity import retry, stop_after_attempt, wait_random_exponential
+from tenacity import (
+    retry,
+    stop_after_attempt,
+    wait_random_exponential,
+)
 from termcolor import colored
 
 
@@ -100,7 +104,9 @@ class FunctionSpecification(BaseModel):
 
         for req_param in self.required or []:
             if req_param not in params:
-                raise ValueError(f"Missing required parameter: {req_param}")
+                raise ValueError(
+                    f"Missing required parameter: {req_param}"
+                )
 
 
 class OpenAIFunctionCaller:
@@ -146,7 +152,8 @@ class OpenAIFunctionCaller:
         self.messages.append({"role": role, "content": content})
 
     @retry(
-        wait=wait_random_exponential(multiplier=1, max=40), stop=stop_after_attempt(3)
+        wait=wait_random_exponential(multiplier=1, max=40),
+        stop=stop_after_attempt(3),
     )
     def chat_completion_request(
         self,
@@ -194,17 +201,22 @@ class OpenAIFunctionCaller:
             elif message["role"] == "user":
                 print(
                     colored(
-                        f"user: {message['content']}\n", role_to_color[message["role"]]
+                        f"user: {message['content']}\n",
+                        role_to_color[message["role"]],
                     )
                 )
-            elif message["role"] == "assistant" and message.get("function_call"):
+            elif message["role"] == "assistant" and message.get(
+                "function_call"
+            ):
                 print(
                     colored(
                         f"assistant: {message['function_call']}\n",
                         role_to_color[message["role"]],
                     )
                 )
-            elif message["role"] == "assistant" and not message.get("function_call"):
+            elif message["role"] == "assistant" and not message.get(
+                "function_call"
+            ):
                 print(
                     colored(
                         f"assistant: {message['content']}\n",
@@ -214,7 +226,10 @@ class OpenAIFunctionCaller:
             elif message["role"] == "tool":
                 print(
                     colored(
-                        f"function ({message['name']}): {message['content']}\n",
+                        (
+                            f"function ({message['name']}):"
+                            f" {message['content']}\n"
+                        ),
                         role_to_color[message["role"]],
                     )
                 )
diff --git a/swarms/models/openai_models.py b/swarms/models/openai_models.py
index fcf4a223..14332ff2 100644
--- a/swarms/models/openai_models.py
+++ b/swarms/models/openai_models.py
@@ -27,7 +27,10 @@ from langchain.llms.base import BaseLLM, create_base_retry_decorator
 from langchain.pydantic_v1 import Field, root_validator
 from langchain.schema import Generation, LLMResult
 from langchain.schema.output import GenerationChunk
-from langchain.utils import get_from_dict_or_env, get_pydantic_field_names
+from langchain.utils import (
+    get_from_dict_or_env,
+    get_pydantic_field_names,
+)
 from langchain.utils.utils import build_extra_kwargs
 
 
@@ -44,7 +47,9 @@ def is_openai_v1() -> bool:
 
 
 def update_token_usage(
-    keys: Set[str], response: Dict[str, Any], token_usage: Dict[str, Any]
+    keys: Set[str],
+    response: Dict[str, Any],
+    token_usage: Dict[str, Any],
 ) -> None:
     """Update token usage."""
     _keys_to_use = keys.intersection(response["usage"])
@@ -62,19 +67,29 @@ def _stream_response_to_generation_chunk(
     return GenerationChunk(
         text=stream_response["choices"][0]["text"],
         generation_info=dict(
-            finish_reason=stream_response["choices"][0].get("finish_reason", None),
-            logprobs=stream_response["choices"][0].get("logprobs", None),
+            finish_reason=stream_response["choices"][0].get(
+                "finish_reason", None
+            ),
+            logprobs=stream_response["choices"][0].get(
+                "logprobs", None
+            ),
         ),
     )
 
 
-def _update_response(response: Dict[str, Any], stream_response: Dict[str, Any]) -> None:
+def _update_response(
+    response: Dict[str, Any], stream_response: Dict[str, Any]
+) -> None:
     """Update response from the stream response."""
-    response["choices"][0]["text"] += stream_response["choices"][0]["text"]
-    response["choices"][0]["finish_reason"] = stream_response["choices"][0].get(
-        "finish_reason", None
-    )
-    response["choices"][0]["logprobs"] = stream_response["choices"][0]["logprobs"]
+    response["choices"][0]["text"] += stream_response["choices"][0][
+        "text"
+    ]
+    response["choices"][0]["finish_reason"] = stream_response[
+        "choices"
+    ][0].get("finish_reason", None)
+    response["choices"][0]["logprobs"] = stream_response["choices"][
+        0
+    ]["logprobs"]
 
 
 def _streaming_response_template() -> Dict[str, Any]:
@@ -105,7 +120,9 @@ def _create_retry_decorator(
         openai.error.ServiceUnavailableError,
     ]
     return create_base_retry_decorator(
-        error_types=errors, max_retries=llm.max_retries, run_manager=run_manager
+        error_types=errors,
+        max_retries=llm.max_retries,
+        run_manager=run_manager,
     )
 
 
@@ -115,7 +132,9 @@ def completion_with_retry(
     **kwargs: Any,
 ) -> Any:
     """Use tenacity to retry the completion call."""
-    retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
+    retry_decorator = _create_retry_decorator(
+        llm, run_manager=run_manager
+    )
 
     @retry_decorator
     def _completion_with_retry(**kwargs: Any) -> Any:
@@ -130,7 +149,9 @@ async def acompletion_with_retry(
     **kwargs: Any,
 ) -> Any:
     """Use tenacity to retry the async completion call."""
-    retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
+    retry_decorator = _create_retry_decorator(
+        llm, run_manager=run_manager
+    )
 
     @retry_decorator
     async def _completion_with_retry(**kwargs: Any) -> Any:
@@ -154,7 +175,9 @@ class BaseOpenAI(BaseLLM):
             attributes["openai_api_base"] = self.openai_api_base
 
         if self.openai_organization != "":
-            attributes["openai_organization"] = self.openai_organization
+            attributes["openai_organization"] = (
+                self.openai_organization
+            )
 
         if self.openai_proxy != "":
             attributes["openai_proxy"] = self.openai_proxy
@@ -193,9 +216,13 @@ class BaseOpenAI(BaseLLM):
     openai_proxy: Optional[str] = None
     batch_size: int = 20
     """Batch size to use when passing multiple documents to generate."""
-    request_timeout: Optional[Union[float, Tuple[float, float]]] = None
+    request_timeout: Optional[Union[float, Tuple[float, float]]] = (
+        None
+    )
     """Timeout for requests to OpenAI completion API. Default is 600 seconds."""
-    logit_bias: Optional[Dict[str, float]] = Field(default_factory=dict)
+    logit_bias: Optional[Dict[str, float]] = Field(
+        default_factory=dict
+    )
     """Adjust the probability of specific tokens being generated."""
     max_retries: int = 6
     """Maximum number of retries to make when generating."""
@@ -272,7 +299,9 @@ class BaseOpenAI(BaseLLM):
         if values["streaming"] and values["n"] > 1:
             raise ValueError("Cannot stream results when n > 1.")
         if values["streaming"] and values["best_of"] > 1:
-            raise ValueError("Cannot stream results when best_of > 1.")
+            raise ValueError(
+                "Cannot stream results when best_of > 1."
+            )
         return values
 
     @property
@@ -304,7 +333,9 @@ class BaseOpenAI(BaseLLM):
         **kwargs: Any,
     ) -> Iterator[GenerationChunk]:
         params = {**self._invocation_params, **kwargs, "stream": True}
-        self.get_sub_prompts(params, [prompt], stop)  # this mutates params
+        self.get_sub_prompts(
+            params, [prompt], stop
+        )  # this mutates params
         for stream_resp in completion_with_retry(
             self, prompt=prompt, run_manager=run_manager, **params
         ):
@@ -315,9 +346,11 @@ class BaseOpenAI(BaseLLM):
                     chunk.text,
                     chunk=chunk,
                     verbose=self.verbose,
-                    logprobs=chunk.generation_info["logprobs"]
-                    if chunk.generation_info
-                    else None,
+                    logprobs=(
+                        chunk.generation_info["logprobs"]
+                        if chunk.generation_info
+                        else None
+                    ),
                 )
 
     async def _astream(
@@ -328,7 +361,9 @@ class BaseOpenAI(BaseLLM):
         **kwargs: Any,
     ) -> AsyncIterator[GenerationChunk]:
         params = {**self._invocation_params, **kwargs, "stream": True}
-        self.get_sub_prompts(params, [prompt], stop)  # this mutate params
+        self.get_sub_prompts(
+            params, [prompt], stop
+        )  # this mutate params
         async for stream_resp in await acompletion_with_retry(
             self, prompt=prompt, run_manager=run_manager, **params
         ):
@@ -339,9 +374,11 @@ class BaseOpenAI(BaseLLM):
                     chunk.text,
                     chunk=chunk,
                     verbose=self.verbose,
-                    logprobs=chunk.generation_info["logprobs"]
-                    if chunk.generation_info
-                    else None,
+                    logprobs=(
+                        chunk.generation_info["logprobs"]
+                        if chunk.generation_info
+                        else None
+                    ),
                 )
 
     def _generate(
@@ -377,10 +414,14 @@ class BaseOpenAI(BaseLLM):
         for _prompts in sub_prompts:
             if self.streaming:
                 if len(_prompts) > 1:
-                    raise ValueError("Cannot stream results with multiple prompts.")
+                    raise ValueError(
+                        "Cannot stream results with multiple prompts."
+                    )
 
                 generation: Optional[GenerationChunk] = None
-                for chunk in self._stream(_prompts[0], stop, run_manager, **kwargs):
+                for chunk in self._stream(
+                    _prompts[0], stop, run_manager, **kwargs
+                ):
                     if generation is None:
                         generation = chunk
                     else:
@@ -389,17 +430,26 @@ class BaseOpenAI(BaseLLM):
                 choices.append(
                     {
                         "text": generation.text,
-                        "finish_reason": generation.generation_info.get("finish_reason")
-                        if generation.generation_info
-                        else None,
-                        "logprobs": generation.generation_info.get("logprobs")
-                        if generation.generation_info
-                        else None,
+                        "finish_reason": (
+                            generation.generation_info.get(
+                                "finish_reason"
+                            )
+                            if generation.generation_info
+                            else None
+                        ),
+                        "logprobs": (
+                            generation.generation_info.get("logprobs")
+                            if generation.generation_info
+                            else None
+                        ),
                     }
                 )
             else:
                 response = completion_with_retry(
-                    self, prompt=_prompts, run_manager=run_manager, **params
+                    self,
+                    prompt=_prompts,
+                    run_manager=run_manager,
+                    **params,
                 )
                 choices.extend(response["choices"])
                 update_token_usage(_keys, response, token_usage)
@@ -424,7 +474,9 @@ class BaseOpenAI(BaseLLM):
         for _prompts in sub_prompts:
             if self.streaming:
                 if len(_prompts) > 1:
-                    raise ValueError("Cannot stream results with multiple prompts.")
+                    raise ValueError(
+                        "Cannot stream results with multiple prompts."
+                    )
 
                 generation: Optional[GenerationChunk] = None
                 async for chunk in self._astream(
@@ -438,17 +490,26 @@ class BaseOpenAI(BaseLLM):
                 choices.append(
                     {
                         "text": generation.text,
-                        "finish_reason": generation.generation_info.get("finish_reason")
-                        if generation.generation_info
-                        else None,
-                        "logprobs": generation.generation_info.get("logprobs")
-                        if generation.generation_info
-                        else None,
+                        "finish_reason": (
+                            generation.generation_info.get(
+                                "finish_reason"
+                            )
+                            if generation.generation_info
+                            else None
+                        ),
+                        "logprobs": (
+                            generation.generation_info.get("logprobs")
+                            if generation.generation_info
+                            else None
+                        ),
                     }
                 )
             else:
                 response = await acompletion_with_retry(
-                    self, prompt=_prompts, run_manager=run_manager, **params
+                    self,
+                    prompt=_prompts,
+                    run_manager=run_manager,
+                    **params,
                 )
                 choices.extend(response["choices"])
                 update_token_usage(_keys, response, token_usage)
@@ -463,14 +524,20 @@ class BaseOpenAI(BaseLLM):
         """Get the sub prompts for llm call."""
         if stop is not None:
             if "stop" in params:
-                raise ValueError("`stop` found in both the input and default params.")
+                raise ValueError(
+                    "`stop` found in both the input and default"
+                    " params."
+                )
             params["stop"] = stop
         if params["max_tokens"] == -1:
             if len(prompts) != 1:
                 raise ValueError(
-                    "max_tokens set to -1 not supported for multiple inputs."
+                    "max_tokens set to -1 not supported for multiple"
+                    " inputs."
                 )
-            params["max_tokens"] = self.max_tokens_for_prompt(prompts[0])
+            params["max_tokens"] = self.max_tokens_for_prompt(
+                prompts[0]
+            )
         sub_prompts = [
             prompts[i : i + self.batch_size]
             for i in range(0, len(prompts), self.batch_size)
@@ -478,7 +545,10 @@ class BaseOpenAI(BaseLLM):
         return sub_prompts
 
     def create_llm_result(
-        self, choices: Any, prompts: List[str], token_usage: Dict[str, int]
+        self,
+        choices: Any,
+        prompts: List[str],
+        token_usage: Dict[str, int],
     ) -> LLMResult:
         """Create the LLMResult from the choices and prompts."""
         generations = []
@@ -496,8 +566,13 @@ class BaseOpenAI(BaseLLM):
                     for choice in sub_choices
                 ]
             )
-        llm_output = {"token_usage": token_usage, "model_name": self.model_name}
-        return LLMResult(generations=generations, llm_output=llm_output)
+        llm_output = {
+            "token_usage": token_usage,
+            "model_name": self.model_name,
+        }
+        return LLMResult(
+            generations=generations, llm_output=llm_output
+        )
 
     @property
     def _invocation_params(self) -> Dict[str, Any]:
@@ -516,7 +591,10 @@ class BaseOpenAI(BaseLLM):
     @property
     def _identifying_params(self) -> Mapping[str, Any]:
         """Get the identifying parameters."""
-        return {**{"model_name": self.model_name}, **self._default_params}
+        return {
+            **{"model_name": self.model_name},
+            **self._default_params,
+        }
 
     @property
     def _llm_type(self) -> str:
@@ -532,16 +610,19 @@ class BaseOpenAI(BaseLLM):
             import tiktoken
         except ImportError:
             raise ImportError(
-                "Could not import tiktoken python package. "
-                "This is needed in order to calculate get_num_tokens. "
-                "Please install it with `pip install tiktoken`."
+                "Could not import tiktoken python package. This is"
+                " needed in order to calculate get_num_tokens. Please"
+                " install it with `pip install tiktoken`."
             )
 
         model_name = self.tiktoken_model_name or self.model_name
         try:
             enc = tiktoken.encoding_for_model(model_name)
         except KeyError:
-            logger.warning("Warning: model not found. Using cl100k_base encoding.")
+            logger.warning(
+                "Warning: model not found. Using cl100k_base"
+                " encoding."
+            )
             model = "cl100k_base"
             enc = tiktoken.get_encoding(model)
 
@@ -602,8 +683,9 @@ class BaseOpenAI(BaseLLM):
 
         if context_size is None:
             raise ValueError(
-                f"Unknown model: {modelname}. Please provide a valid OpenAI model name."
-                "Known models are: " + ", ".join(model_token_mapping.keys())
+                f"Unknown model: {modelname}. Please provide a valid"
+                " OpenAI model name.Known models are: "
+                + ", ".join(model_token_mapping.keys())
             )
 
         return context_size
@@ -649,7 +731,10 @@ class OpenAI(BaseOpenAI):
 
     @property
     def _invocation_params(self) -> Dict[str, Any]:
-        return {**{"model": self.model_name}, **super()._invocation_params}
+        return {
+            **{"model": self.model_name},
+            **super()._invocation_params,
+        }
 
 
 class AzureOpenAI(BaseOpenAI):
@@ -723,6 +808,21 @@ class OpenAIChat(BaseLLM):
     Any parameters that are valid to be passed to the openai.create call can be passed
     in, even if not explicitly saved on this class.
 
+    Args:
+
+        model_name: The model name to use.
+        model_kwargs: Any additional kwargs to pass to the model.
+        openai_api_key: The OpenAI API key to use.
+        openai_api_base: The OpenAI API base to use.
+        openai_proxy: The OpenAI proxy to use.
+        max_retries: The maximum number of retries to make when generating.
+        prefix_messages: The prefix messages to use.
+        streaming: Whether to stream the results or not.
+        allowed_special: Set of special tokens that are allowed。
+        disallowed_special: Set of special tokens that are not allowed。
+
+
+
     Example:
         .. code-block:: python
 
@@ -731,13 +831,10 @@ class OpenAIChat(BaseLLM):
     """
 
     client: Any  #: :meta private:
-    model_name: str = "gpt-3.5-turbo"
-    """Model name to use."""
+    model_name: str = "gpt-3.5-turbo-1106"
     model_kwargs: Dict[str, Any] = Field(default_factory=dict)
-    """Holds any model parameters valid for `create` call not explicitly specified."""
     openai_api_key: Optional[str] = None
     openai_api_base: Optional[str] = None
-    # to support explicit proxy for OpenAI
     openai_proxy: Optional[str] = None
     max_retries: int = 6
     """Maximum number of retries to make when generating."""
@@ -753,13 +850,17 @@ class OpenAIChat(BaseLLM):
     @root_validator(pre=True)
     def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
         """Build extra kwargs from additional params that were passed in."""
-        all_required_field_names = {field.alias for field in cls.__fields__.values()}
+        all_required_field_names = {
+            field.alias for field in cls.__fields__.values()
+        }
 
         extra = values.get("model_kwargs", {})
         for field_name in list(values):
             if field_name not in all_required_field_names:
                 if field_name in extra:
-                    raise ValueError(f"Found {field_name} supplied twice.")
+                    raise ValueError(
+                        f"Found {field_name} supplied twice."
+                    )
                 extra[field_name] = values.pop(field_name)
         values["model_kwargs"] = extra
         return values
@@ -783,7 +884,10 @@ class OpenAIChat(BaseLLM):
             default="",
         )
         openai_organization = get_from_dict_or_env(
-            values, "openai_organization", "OPENAI_ORGANIZATION", default=""
+            values,
+            "openai_organization",
+            "OPENAI_ORGANIZATION",
+            default="",
         )
         try:
             import openai
@@ -804,9 +908,10 @@ class OpenAIChat(BaseLLM):
             values["client"] = openai.ChatCompletion
         except AttributeError:
             raise ValueError(
-                "`openai` has no `ChatCompletion` attribute, this is likely "
-                "due to an old version of the openai package. Try upgrading it "
-                "with `pip install --upgrade openai`."
+                "`openai` has no `ChatCompletion` attribute, this is"
+                " likely due to an old version of the openai package."
+                " Try upgrading it with `pip install --upgrade"
+                " openai`."
             )
         return values
 
@@ -820,13 +925,22 @@ class OpenAIChat(BaseLLM):
     ) -> Tuple:
         if len(prompts) > 1:
             raise ValueError(
-                f"OpenAIChat currently only supports single prompt, got {prompts}"
+                "OpenAIChat currently only supports single prompt,"
+                f" got {prompts}"
             )
-        messages = self.prefix_messages + [{"role": "user", "content": prompts[0]}]
-        params: Dict[str, Any] = {**{"model": self.model_name}, **self._default_params}
+        messages = self.prefix_messages + [
+            {"role": "user", "content": prompts[0]}
+        ]
+        params: Dict[str, Any] = {
+            **{"model": self.model_name},
+            **self._default_params,
+        }
         if stop is not None:
             if "stop" in params:
-                raise ValueError("`stop` found in both the input and default params.")
+                raise ValueError(
+                    "`stop` found in both the input and default"
+                    " params."
+                )
             params["stop"] = stop
         if params.get("max_tokens") == -1:
             # for ChatGPT api, omitting max_tokens is equivalent to having no limit
@@ -845,7 +959,9 @@ class OpenAIChat(BaseLLM):
         for stream_resp in completion_with_retry(
             self, messages=messages, run_manager=run_manager, **params
         ):
-            token = stream_resp["choices"][0]["delta"].get("content", "")
+            token = stream_resp["choices"][0]["delta"].get(
+                "content", ""
+            )
             chunk = GenerationChunk(text=token)
             yield chunk
             if run_manager:
@@ -863,7 +979,9 @@ class OpenAIChat(BaseLLM):
         async for stream_resp in await acompletion_with_retry(
             self, messages=messages, run_manager=run_manager, **params
         ):
-            token = stream_resp["choices"][0]["delta"].get("content", "")
+            token = stream_resp["choices"][0]["delta"].get(
+                "content", ""
+            )
             chunk = GenerationChunk(text=token)
             yield chunk
             if run_manager:
@@ -878,7 +996,9 @@ class OpenAIChat(BaseLLM):
     ) -> LLMResult:
         if self.streaming:
             generation: Optional[GenerationChunk] = None
-            for chunk in self._stream(prompts[0], stop, run_manager, **kwargs):
+            for chunk in self._stream(
+                prompts[0], stop, run_manager, **kwargs
+            ):
                 if generation is None:
                     generation = chunk
                 else:
@@ -897,7 +1017,13 @@ class OpenAIChat(BaseLLM):
         }
         return LLMResult(
             generations=[
-                [Generation(text=full_response["choices"][0]["message"]["content"])]
+                [
+                    Generation(
+                        text=full_response["choices"][0]["message"][
+                            "content"
+                        ]
+                    )
+                ]
             ],
             llm_output=llm_output,
         )
@@ -911,7 +1037,9 @@ class OpenAIChat(BaseLLM):
     ) -> LLMResult:
         if self.streaming:
             generation: Optional[GenerationChunk] = None
-            async for chunk in self._astream(prompts[0], stop, run_manager, **kwargs):
+            async for chunk in self._astream(
+                prompts[0], stop, run_manager, **kwargs
+            ):
                 if generation is None:
                     generation = chunk
                 else:
@@ -930,7 +1058,13 @@ class OpenAIChat(BaseLLM):
         }
         return LLMResult(
             generations=[
-                [Generation(text=full_response["choices"][0]["message"]["content"])]
+                [
+                    Generation(
+                        text=full_response["choices"][0]["message"][
+                            "content"
+                        ]
+                    )
+                ]
             ],
             llm_output=llm_output,
         )
@@ -938,7 +1072,10 @@ class OpenAIChat(BaseLLM):
     @property
     def _identifying_params(self) -> Mapping[str, Any]:
         """Get the identifying parameters."""
-        return {**{"model_name": self.model_name}, **self._default_params}
+        return {
+            **{"model_name": self.model_name},
+            **self._default_params,
+        }
 
     @property
     def _llm_type(self) -> str:
@@ -954,9 +1091,9 @@ class OpenAIChat(BaseLLM):
             import tiktoken
         except ImportError:
             raise ImportError(
-                "Could not import tiktoken python package. "
-                "This is needed in order to calculate get_num_tokens. "
-                "Please install it with `pip install tiktoken`."
+                "Could not import tiktoken python package. This is"
+                " needed in order to calculate get_num_tokens. Please"
+                " install it with `pip install tiktoken`."
             )
 
         enc = tiktoken.encoding_for_model(self.model_name)
diff --git a/swarms/models/palm.py b/swarms/models/palm.py
index ec8aafd6..d61d4856 100644
--- a/swarms/models/palm.py
+++ b/swarms/models/palm.py
@@ -37,11 +37,19 @@ def _create_retry_decorator() -> Callable[[Any], Any]:
     return retry(
         reraise=True,
         stop=stop_after_attempt(max_retries),
-        wait=wait_exponential(multiplier=multiplier, min=min_seconds, max=max_seconds),
+        wait=wait_exponential(
+            multiplier=multiplier, min=min_seconds, max=max_seconds
+        ),
         retry=(
-            retry_if_exception_type(google.api_core.exceptions.ResourceExhausted)
-            | retry_if_exception_type(google.api_core.exceptions.ServiceUnavailable)
-            | retry_if_exception_type(google.api_core.exceptions.GoogleAPIError)
+            retry_if_exception_type(
+                google.api_core.exceptions.ResourceExhausted
+            )
+            | retry_if_exception_type(
+                google.api_core.exceptions.ServiceUnavailable
+            )
+            | retry_if_exception_type(
+                google.api_core.exceptions.GoogleAPIError
+            )
         ),
         before_sleep=before_sleep_log(logger, logging.WARNING),
     )
@@ -64,7 +72,9 @@ def _strip_erroneous_leading_spaces(text: str) -> str:
     The PaLM API will sometimes erroneously return a single leading space in all
     lines > 1. This function strips that space.
     """
-    has_leading_space = all(not line or line[0] == " " for line in text.split("\n")[1:])
+    has_leading_space = all(
+        not line or line[0] == " " for line in text.split("\n")[1:]
+    )
     if has_leading_space:
         return text.replace("\n ", "\n")
     else:
@@ -106,23 +116,37 @@ class GooglePalm(BaseLLM, BaseModel):
             genai.configure(api_key=google_api_key)
         except ImportError:
             raise ImportError(
-                "Could not import google-generativeai python package. "
-                "Please install it with `pip install google-generativeai`."
+                "Could not import google-generativeai python package."
+                " Please install it with `pip install"
+                " google-generativeai`."
             )
 
         values["client"] = genai
 
-        if values["temperature"] is not None and not 0 <= values["temperature"] <= 1:
-            raise ValueError("temperature must be in the range [0.0, 1.0]")
+        if (
+            values["temperature"] is not None
+            and not 0 <= values["temperature"] <= 1
+        ):
+            raise ValueError(
+                "temperature must be in the range [0.0, 1.0]"
+            )
 
-        if values["top_p"] is not None and not 0 <= values["top_p"] <= 1:
+        if (
+            values["top_p"] is not None
+            and not 0 <= values["top_p"] <= 1
+        ):
             raise ValueError("top_p must be in the range [0.0, 1.0]")
 
         if values["top_k"] is not None and values["top_k"] <= 0:
             raise ValueError("top_k must be positive")
 
-        if values["max_output_tokens"] is not None and values["max_output_tokens"] <= 0:
-            raise ValueError("max_output_tokens must be greater than zero")
+        if (
+            values["max_output_tokens"] is not None
+            and values["max_output_tokens"] <= 0
+        ):
+            raise ValueError(
+                "max_output_tokens must be greater than zero"
+            )
 
         return values
 
@@ -151,8 +175,12 @@ class GooglePalm(BaseLLM, BaseModel):
             prompt_generations = []
             for candidate in completion.candidates:
                 raw_text = candidate["output"]
-                stripped_text = _strip_erroneous_leading_spaces(raw_text)
-                prompt_generations.append(Generation(text=stripped_text))
+                stripped_text = _strip_erroneous_leading_spaces(
+                    raw_text
+                )
+                prompt_generations.append(
+                    Generation(text=stripped_text)
+                )
             generations.append(prompt_generations)
 
         return LLMResult(generations=generations)
diff --git a/swarms/models/pegasus.py b/swarms/models/pegasus.py
index e388d40c..b2f43980 100644
--- a/swarms/models/pegasus.py
+++ b/swarms/models/pegasus.py
@@ -34,16 +34,22 @@ class PegasusEmbedding:
     """
 
     def __init__(
-        self, modality: str, multi_process: bool = False, n_processes: int = 4
+        self,
+        modality: str,
+        multi_process: bool = False,
+        n_processes: int = 4,
     ):
         self.modality = modality
         self.multi_process = multi_process
         self.n_processes = n_processes
         try:
-            self.pegasus = Pegasus(modality, multi_process, n_processes)
+            self.pegasus = Pegasus(
+                modality, multi_process, n_processes
+            )
         except Exception as e:
             logging.error(
-                f"Failed to initialize Pegasus with modality: {modality}: {e}"
+                "Failed to initialize Pegasus with modality:"
+                f" {modality}: {e}"
             )
             raise
 
@@ -52,5 +58,7 @@ class PegasusEmbedding:
         try:
             return self.pegasus.embed(data)
         except Exception as e:
-            logging.error(f"Failed to generate embeddings. Error: {e}")
+            logging.error(
+                f"Failed to generate embeddings. Error: {e}"
+            )
             raise
diff --git a/swarms/models/petals.py b/swarms/models/petals.py
index 189c2477..7abc4590 100644
--- a/swarms/models/petals.py
+++ b/swarms/models/petals.py
@@ -38,6 +38,8 @@ class Petals:
     def __call__(self, prompt):
         """Generate text using the Petals API."""
         params = self._default_params()
-        inputs = self.tokenizer(prompt, return_tensors="pt")["input_ids"]
+        inputs = self.tokenizer(prompt, return_tensors="pt")[
+            "input_ids"
+        ]
         outputs = self.model.generate(inputs, **params)
         return self.tokenizer.decode(outputs[0])
diff --git a/swarms/models/sam.py b/swarms/models/sam.py
new file mode 100644
index 00000000..866c79ee
--- /dev/null
+++ b/swarms/models/sam.py
@@ -0,0 +1,315 @@
+import cv2
+import numpy as np
+from PIL import Image
+from transformers import (
+    SamImageProcessor,
+    SamModel,
+    SamProcessor,
+    pipeline,
+)
+
+try:
+    import cv2
+    import supervision as sv
+except ImportError:
+    print("Please install supervision and cv")
+
+
+from enum import Enum
+
+
+class FeatureType(Enum):
+    """
+    An enumeration to represent the types of features for mask adjustment in image
+    segmentation.
+    """
+
+    ISLAND = "ISLAND"
+    HOLE = "HOLE"
+
+    @classmethod
+    def list(cls):
+        return list(map(lambda c: c.value, cls))
+
+
+def compute_mask_iou_vectorized(masks: np.ndarray) -> np.ndarray:
+    """
+    Vectorized computation of the Intersection over Union (IoU) for all pairs of masks.
+
+    Parameters:
+        masks (np.ndarray): A 3D numpy array with shape `(N, H, W)`, where `N` is the
+            number of masks, `H` is the height, and `W` is the width.
+
+    Returns:
+        np.ndarray: A 2D numpy array of shape `(N, N)` where each element `[i, j]` is
+            the IoU between masks `i` and `j`.
+
+    Raises:
+        ValueError: If any of the masks is found to be empty.
+    """
+    if np.any(masks.sum(axis=(1, 2)) == 0):
+        raise ValueError(
+            "One or more masks are empty. Please filter out empty"
+            " masks before using `compute_iou_vectorized` function."
+        )
+
+    masks_bool = masks.astype(bool)
+    masks_flat = masks_bool.reshape(masks.shape[0], -1)
+    intersection = np.logical_and(
+        masks_flat[:, None], masks_flat[None, :]
+    ).sum(axis=2)
+    union = np.logical_or(
+        masks_flat[:, None], masks_flat[None, :]
+    ).sum(axis=2)
+    iou_matrix = intersection / union
+    return iou_matrix
+
+
+def mask_non_max_suppression(
+    masks: np.ndarray, iou_threshold: float = 0.6
+) -> np.ndarray:
+    """
+    Performs Non-Max Suppression on a set of masks by prioritizing larger masks and
+        removing smaller masks that overlap significantly.
+
+    When the IoU between two masks exceeds the specified threshold, the smaller mask
+    (in terms of area) is discarded. This process is repeated for each pair of masks,
+    effectively filtering out masks that are significantly overlapped by larger ones.
+
+    Parameters:
+        masks (np.ndarray): A 3D numpy array with shape `(N, H, W)`, where `N` is the
+            number of masks, `H` is the height, and `W` is the width.
+        iou_threshold (float): The IoU threshold for determining significant overlap.
+
+    Returns:
+        np.ndarray: A 3D numpy array of filtered masks.
+    """
+    num_masks = masks.shape[0]
+    areas = masks.sum(axis=(1, 2))
+    sorted_idx = np.argsort(-areas)
+    keep_mask = np.ones(num_masks, dtype=bool)
+    iou_matrix = compute_mask_iou_vectorized(masks)
+    for i in range(num_masks):
+        if not keep_mask[sorted_idx[i]]:
+            continue
+
+        overlapping_masks = iou_matrix[sorted_idx[i]] > iou_threshold
+        overlapping_masks[sorted_idx[i]] = False
+        keep_mask[sorted_idx] = np.logical_and(
+            keep_mask[sorted_idx], ~overlapping_masks
+        )
+
+    return masks[keep_mask]
+
+
+def filter_masks_by_relative_area(
+    masks: np.ndarray,
+    minimum_area: float = 0.01,
+    maximum_area: float = 1.0,
+) -> np.ndarray:
+    """
+    Filters masks based on their relative area within the total area of each mask.
+
+    Parameters:
+        masks (np.ndarray): A 3D numpy array with shape `(N, H, W)`, where `N` is the
+            number of masks, `H` is the height, and `W` is the width.
+        minimum_area (float): The minimum relative area threshold. Must be between `0`
+            and `1`.
+        maximum_area (float): The maximum relative area threshold. Must be between `0`
+            and `1`.
+
+    Returns:
+        np.ndarray: A 3D numpy array containing masks that fall within the specified
+            relative area range.
+
+    Raises:
+        ValueError: If `minimum_area` or `maximum_area` are outside the `0` to `1`
+            range, or if `minimum_area` is greater than `maximum_area`.
+    """
+
+    if not (isinstance(masks, np.ndarray) and masks.ndim == 3):
+        raise ValueError("Input must be a 3D numpy array.")
+
+    if not (0 <= minimum_area <= 1) or not (0 <= maximum_area <= 1):
+        raise ValueError(
+            "`minimum_area` and `maximum_area` must be between 0"
+            " and 1."
+        )
+
+    if minimum_area > maximum_area:
+        raise ValueError(
+            "`minimum_area` must be less than or equal to"
+            " `maximum_area`."
+        )
+
+    total_area = masks.shape[1] * masks.shape[2]
+    relative_areas = masks.sum(axis=(1, 2)) / total_area
+    return masks[
+        (relative_areas >= minimum_area)
+        & (relative_areas <= maximum_area)
+    ]
+
+
+def adjust_mask_features_by_relative_area(
+    mask: np.ndarray,
+    area_threshold: float,
+    feature_type: FeatureType = FeatureType.ISLAND,
+) -> np.ndarray:
+    """
+    Adjusts a mask by removing small islands or filling small holes based on a relative
+    area threshold.
+
+    !!! warning
+
+        Running this function on a mask with small islands may result in empty masks.
+
+    Parameters:
+        mask (np.ndarray): A 2D numpy array with shape `(H, W)`, where `H` is the
+            height, and `W` is the width.
+        area_threshold (float): Threshold for relative area to remove or fill features.
+        feature_type (FeatureType): Type of feature to adjust (`ISLAND` for removing
+            islands, `HOLE` for filling holes).
+
+    Returns:
+        np.ndarray: A 2D numpy array containing mask.
+    """
+    height, width = mask.shape
+    total_area = width * height
+
+    mask = np.uint8(mask * 255)
+    operation = (
+        cv2.RETR_EXTERNAL
+        if feature_type == FeatureType.ISLAND
+        else cv2.RETR_CCOMP
+    )
+    contours, _ = cv2.findContours(
+        mask, operation, cv2.CHAIN_APPROX_SIMPLE
+    )
+
+    for contour in contours:
+        area = cv2.contourArea(contour)
+        relative_area = area / total_area
+        if relative_area < area_threshold:
+            cv2.drawContours(
+                image=mask,
+                contours=[contour],
+                contourIdx=-1,
+                color=(
+                    0 if feature_type == FeatureType.ISLAND else 255
+                ),
+                thickness=-1,
+            )
+    return np.where(mask > 0, 1, 0).astype(bool)
+
+
+def masks_to_marks(masks: np.ndarray) -> sv.Detections:
+    """
+    Converts a set of masks to a marks (sv.Detections) object.
+
+    Parameters:
+        masks (np.ndarray): A 3D numpy array with shape `(N, H, W)`, where `N` is the
+            number of masks, `H` is the height, and `W` is the width.
+
+    Returns:
+        sv.Detections: An object containing the masks and their bounding box
+            coordinates.
+    """
+    return sv.Detections(
+        mask=masks, xyxy=sv.mask_to_xyxy(masks=masks)
+    )
+
+
+def refine_marks(
+    marks: sv.Detections,
+    maximum_hole_area: float = 0.01,
+    maximum_island_area: float = 0.01,
+    minimum_mask_area: float = 0.02,
+    maximum_mask_area: float = 1.0,
+) -> sv.Detections:
+    """
+    Refines a set of masks by removing small islands and holes, and filtering by mask
+    area.
+
+    Parameters:
+        marks (sv.Detections): An object containing the masks and their bounding box
+            coordinates.
+        maximum_hole_area (float): The maximum relative area of holes to be filled in
+            each mask.
+        maximum_island_area (float): The maximum relative area of islands to be removed
+            from each mask.
+        minimum_mask_area (float): The minimum relative area for a mask to be retained.
+        maximum_mask_area (float): The maximum relative area for a mask to be retained.
+
+    Returns:
+        sv.Detections: An object containing the masks and their bounding box
+            coordinates.
+    """
+    result_masks = []
+    for mask in marks.mask:
+        mask = adjust_mask_features_by_relative_area(
+            mask=mask,
+            area_threshold=maximum_island_area,
+            feature_type=FeatureType.ISLAND,
+        )
+        mask = adjust_mask_features_by_relative_area(
+            mask=mask,
+            area_threshold=maximum_hole_area,
+            feature_type=FeatureType.HOLE,
+        )
+        if np.any(mask):
+            result_masks.append(mask)
+    result_masks = np.array(result_masks)
+    result_masks = filter_masks_by_relative_area(
+        masks=result_masks,
+        minimum_area=minimum_mask_area,
+        maximum_area=maximum_mask_area,
+    )
+    return sv.Detections(
+        mask=result_masks, xyxy=sv.mask_to_xyxy(masks=result_masks)
+    )
+
+
+class SegmentAnythingMarkGenerator:
+    """
+    A class for performing image segmentation using a specified model.
+
+    Parameters:
+        device (str): The device to run the model on (e.g., 'cpu', 'cuda').
+        model_name (str): The name of the model to be loaded. Defaults to
+                          'facebook/sam-vit-huge'.
+    """
+
+    def __init__(
+        self,
+        device: str = "cpu",
+        model_name: str = "facebook/sam-vit-huge",
+    ):
+        self.model = SamModel.from_pretrained(model_name).to(device)
+        self.processor = SamProcessor.from_pretrained(model_name)
+        self.image_processor = SamImageProcessor.from_pretrained(
+            model_name
+        )
+        self.pipeline = pipeline(
+            task="mask-generation",
+            model=self.model,
+            image_processor=self.image_processor,
+            device=device,
+        )
+
+    def run(self, image: np.ndarray) -> sv.Detections:
+        """
+        Generate image segmentation marks.
+
+        Parameters:
+            image (np.ndarray): The image to be marked in BGR format.
+
+        Returns:
+            sv.Detections: An object containing the segmentation masks and their
+                corresponding bounding box coordinates.
+        """
+        image = Image.fromarray(
+            cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
+        )
+        outputs = self.pipeline(image, points_per_batch=64)
+        masks = np.array(outputs["masks"])
+        return masks_to_marks(masks=masks)
diff --git a/swarms/models/simple_ada.py b/swarms/models/simple_ada.py
index 3662dda2..e9a599d0 100644
--- a/swarms/models/simple_ada.py
+++ b/swarms/models/simple_ada.py
@@ -4,7 +4,9 @@ from openai import OpenAI
 client = OpenAI()
 
 
-def get_ada_embeddings(text: str, model: str = "text-embedding-ada-002"):
+def get_ada_embeddings(
+    text: str, model: str = "text-embedding-ada-002"
+):
     """
     Simple function to get embeddings from ada
 
@@ -16,4 +18,6 @@ def get_ada_embeddings(text: str, model: str = "text-embedding-ada-002"):
 
     text = text.replace("\n", " ")
 
-    return client.embeddings.create(input=[text], model=model)["data"][0]["embedding"]
+    return client.embeddings.create(input=[text], model=model)[
+        "data"
+    ][0]["embedding"]
diff --git a/swarms/models/speecht5.py b/swarms/models/speecht5.py
index e98036ac..cc6ef931 100644
--- a/swarms/models/speecht5.py
+++ b/swarms/models/speecht5.py
@@ -87,10 +87,18 @@ class SpeechT5:
         self.model_name = model_name
         self.vocoder_name = vocoder_name
         self.dataset_name = dataset_name
-        self.processor = SpeechT5Processor.from_pretrained(self.model_name)
-        self.model = SpeechT5ForTextToSpeech.from_pretrained(self.model_name)
-        self.vocoder = SpeechT5HifiGan.from_pretrained(self.vocoder_name)
-        self.embeddings_dataset = load_dataset(self.dataset_name, split="validation")
+        self.processor = SpeechT5Processor.from_pretrained(
+            self.model_name
+        )
+        self.model = SpeechT5ForTextToSpeech.from_pretrained(
+            self.model_name
+        )
+        self.vocoder = SpeechT5HifiGan.from_pretrained(
+            self.vocoder_name
+        )
+        self.embeddings_dataset = load_dataset(
+            self.dataset_name, split="validation"
+        )
 
     def __call__(self, text: str, speaker_id: float = 7306):
         """Call the model on some text and return the speech."""
@@ -99,7 +107,9 @@ class SpeechT5:
         ).unsqueeze(0)
         inputs = self.processor(text=text, return_tensors="pt")
         speech = self.model.generate_speech(
-            inputs["input_ids"], speaker_embedding, vocoder=self.vocoder
+            inputs["input_ids"],
+            speaker_embedding,
+            vocoder=self.vocoder,
         )
         return speech
 
@@ -110,18 +120,26 @@ class SpeechT5:
     def set_model(self, model_name: str):
         """Set the model to a new model."""
         self.model_name = model_name
-        self.processor = SpeechT5Processor.from_pretrained(self.model_name)
-        self.model = SpeechT5ForTextToSpeech.from_pretrained(self.model_name)
+        self.processor = SpeechT5Processor.from_pretrained(
+            self.model_name
+        )
+        self.model = SpeechT5ForTextToSpeech.from_pretrained(
+            self.model_name
+        )
 
     def set_vocoder(self, vocoder_name):
         """Set the vocoder to a new vocoder."""
         self.vocoder_name = vocoder_name
-        self.vocoder = SpeechT5HifiGan.from_pretrained(self.vocoder_name)
+        self.vocoder = SpeechT5HifiGan.from_pretrained(
+            self.vocoder_name
+        )
 
     def set_embeddings_dataset(self, dataset_name):
         """Set the embeddings dataset to a new dataset."""
         self.dataset_name = dataset_name
-        self.embeddings_dataset = load_dataset(self.dataset_name, split="validation")
+        self.embeddings_dataset = load_dataset(
+            self.dataset_name, split="validation"
+        )
 
     # Feature 1: Get sampling rate
     def get_sampling_rate(self):
@@ -144,7 +162,9 @@ class SpeechT5:
     # Feature 4: Change dataset split (train, validation, test)
     def change_dataset_split(self, split="train"):
         """Change dataset split (train, validation, test)."""
-        self.embeddings_dataset = load_dataset(self.dataset_name, split=split)
+        self.embeddings_dataset = load_dataset(
+            self.dataset_name, split=split
+        )
 
     # Feature 5: Load a custom speaker embedding (xvector) for the text
     def load_custom_embedding(self, xvector):
diff --git a/swarms/models/ssd_1b.py b/swarms/models/ssd_1b.py
index caeba3fc..d3b9086b 100644
--- a/swarms/models/ssd_1b.py
+++ b/swarms/models/ssd_1b.py
@@ -96,7 +96,9 @@ class SSD1B:
         byte_array = byte_stream.getvalue()
         return byte_array
 
-    @backoff.on_exception(backoff.expo, Exception, max_time=max_time_seconds)
+    @backoff.on_exception(
+        backoff.expo, Exception, max_time=max_time_seconds
+    )
     def __call__(self, task: str, neg_prompt: str):
         """
         Text to image conversion using the SSD1B API
@@ -124,7 +126,9 @@ class SSD1B:
         if task in self.cache:
             return self.cache[task]
         try:
-            img = self.pipe(prompt=task, neg_prompt=neg_prompt).images[0]
+            img = self.pipe(
+                prompt=task, neg_prompt=neg_prompt
+            ).images[0]
 
             # Generate a unique filename for the image
             img_name = f"{uuid.uuid4()}.{self.image_format}"
@@ -141,8 +145,8 @@ class SSD1B:
             print(
                 colored(
                     (
-                        f"Error running SSD1B: {error} try optimizing your api key and"
-                        " or try again"
+                        f"Error running SSD1B: {error} try optimizing"
+                        " your api key and or try again"
                     ),
                     "red",
                 )
@@ -167,8 +171,7 @@ class SSD1B:
         """Print the SSD1B dashboard"""
         print(
             colored(
-                (
-                    f"""SSD1B Dashboard: 
+                f"""SSD1B Dashboard: 
                     --------------------
 
                     Model: {self.model}
@@ -184,13 +187,14 @@ class SSD1B:
                     --------------------
                     
                     
-                    """
-                ),
+                    """,
                 "green",
             )
         )
 
-    def process_batch_concurrently(self, tasks: List[str], max_workers: int = 5):
+    def process_batch_concurrently(
+        self, tasks: List[str], max_workers: int = 5
+    ):
         """
 
         Process a batch of tasks concurrently
@@ -211,10 +215,16 @@ class SSD1B:
         >>> print(results)
 
         """
-        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
-            future_to_task = {executor.submit(self, task): task for task in tasks}
+        with concurrent.futures.ThreadPoolExecutor(
+            max_workers=max_workers
+        ) as executor:
+            future_to_task = {
+                executor.submit(self, task): task for task in tasks
+            }
             results = []
-            for future in concurrent.futures.as_completed(future_to_task):
+            for future in concurrent.futures.as_completed(
+                future_to_task
+            ):
                 task = future_to_task[future]
                 try:
                     img = future.result()
@@ -225,14 +235,28 @@ class SSD1B:
                     print(
                         colored(
                             (
-                                f"Error running SSD1B: {error} try optimizing your api key and"
-                                " or try again"
+                                f"Error running SSD1B: {error} try"
+                                " optimizing your api key and or try"
+                                " again"
                             ),
                             "red",
                         )
                     )
-                    print(colored(f"Error running SSD1B: {error.http_status}", "red"))
-                    print(colored(f"Error running SSD1B: {error.error}", "red"))
+                    print(
+                        colored(
+                            (
+                                "Error running SSD1B:"
+                                f" {error.http_status}"
+                            ),
+                            "red",
+                        )
+                    )
+                    print(
+                        colored(
+                            f"Error running SSD1B: {error.error}",
+                            "red",
+                        )
+                    )
                     raise error
 
     def _generate_uuid(self):
@@ -247,7 +271,9 @@ class SSD1B:
         """Str method for the SSD1B class"""
         return f"SSD1B(image_url={self.image_url})"
 
-    @backoff.on_exception(backoff.expo, Exception, max_tries=max_retries)
+    @backoff.on_exception(
+        backoff.expo, Exception, max_tries=max_retries
+    )
     def rate_limited_call(self, task: str):
         """Rate limited call to the SSD1B API"""
         return self.__call__(task)
diff --git a/swarms/models/stable_diffusion.py b/swarms/models/stable_diffusion.py
new file mode 100644
index 00000000..7b363d02
--- /dev/null
+++ b/swarms/models/stable_diffusion.py
@@ -0,0 +1,154 @@
+import base64
+import os
+import requests
+import uuid
+import shutil
+from dotenv import load_dotenv
+from typing import List
+
+load_dotenv()
+
+stable_api_key = os.environ.get("STABLE_API_KEY")
+
+
+class StableDiffusion:
+    """
+    A class to interact with the Stable Diffusion API for generating images from text prompts.
+
+    Attributes:
+    -----------
+    api_key : str
+        The API key for accessing the Stable Diffusion API.
+    api_host : str
+        The host URL for the Stable Diffusion API.
+    engine_id : str
+        The engine ID for the Stable Diffusion API.
+    cfg_scale : int
+        Configuration scale for image generation.
+    height : int
+        The height of the generated image.
+    width : int
+        The width of the generated image.
+    samples : int
+        The number of samples to generate.
+    steps : int
+        The number of steps for the generation process.
+    output_dir : str
+        Directory where the generated images will be saved.
+
+    Methods:
+    --------
+    __init__(self, api_key: str, api_host: str, cfg_scale: int, height: int, width: int, samples: int, steps: int):
+        Initializes the StableDiffusion instance with provided parameters.
+
+    generate_image(self, task: str) -> List[str]:
+        Generates an image based on the provided text prompt and returns the paths of the saved images.
+    """
+
+    def __init__(
+        self,
+        api_key: str = stable_api_key,
+        api_host: str = "https://api.stability.ai",
+        cfg_scale: int = 7,
+        height: int = 1024,
+        width: int = 1024,
+        samples: int = 1,
+        steps: int = 30,
+    ):
+        """
+        Initialize the StableDiffusion class with API configurations.
+
+        Parameters:
+        -----------
+        api_key : str
+            The API key for accessing the Stable Diffusion API.
+        api_host : str
+            The host URL for the Stable Diffusion API.
+        cfg_scale : int
+            Configuration scale for image generation.
+        height : int
+            The height of the generated image.
+        width : int
+            The width of the generated image.
+        samples : int
+            The number of samples to generate.
+        steps : int
+            The number of steps for the generation process.
+        """
+        self.api_key = api_key
+        self.api_host = api_host
+        self.engine_id = "stable-diffusion-v1-6"
+        self.cfg_scale = cfg_scale
+        self.height = height
+        self.width = width
+        self.samples = samples
+        self.steps = steps
+        self.headers = {
+            "Authorization": f"Bearer {self.api_key}",
+            "Content-Type": "application/json",
+            "Accept": "application/json",
+        }
+        self.output_dir = "images"
+        os.makedirs(self.output_dir, exist_ok=True)
+
+    def run(self, task: str) -> List[str]:
+        """
+        Generates an image based on a given text prompt.
+
+        Parameters:
+        -----------
+        task : str
+            The text prompt based on which the image will be generated.
+
+        Returns:
+        --------
+        List[str]:
+            A list of file paths where the generated images are saved.
+
+        Raises:
+        -------
+        Exception:
+            If the API request fails and returns a non-200 response.
+        """
+        response = requests.post(
+            f"{self.api_host}/v1/generation/{self.engine_id}/text-to-image",
+            headers=self.headers,
+            json={
+                "text_prompts": [{"text": task}],
+                "cfg_scale": self.cfg_scale,
+                "height": self.height,
+                "width": self.width,
+                "samples": self.samples,
+                "steps": self.steps,
+            },
+        )
+
+        if response.status_code != 200:
+            raise Exception(f"Non-200 response: {response.text}")
+
+        data = response.json()
+        image_paths = []
+        for i, image in enumerate(data["artifacts"]):
+            unique_id = uuid.uuid4()  # Generate a unique identifier
+            image_path = os.path.join(
+                self.output_dir, f"{unique_id}_v1_txt2img_{i}.png"
+            )
+            with open(image_path, "wb") as f:
+                f.write(base64.b64decode(image["base64"]))
+            image_paths.append(image_path)
+
+        return image_paths
+
+    def generate_and_move_image(self, prompt, iteration, folder_path):
+        # Generate the image
+        image_paths = self.run(prompt)
+        if not image_paths:
+            return None
+
+        # Move the image to the specified folder
+        src_image_path = image_paths[0]
+        dst_image_path = os.path.join(
+            folder_path, f"image_{iteration}.jpg"
+        )
+        shutil.move(src_image_path, dst_image_path)
+        return dst_image_path
diff --git a/swarms/models/timm.py b/swarms/models/timm.py
index 9947ec7b..d1c42165 100644
--- a/swarms/models/timm.py
+++ b/swarms/models/timm.py
@@ -34,7 +34,9 @@ class TimmModel:
         """Retrieve the list of supported models from timm."""
         return timm.list_models()
 
-    def _create_model(self, model_info: TimmModelInfo) -> torch.nn.Module:
+    def _create_model(
+        self, model_info: TimmModelInfo
+    ) -> torch.nn.Module:
         """
         Create a model instance from timm with specified parameters.
 
diff --git a/swarms/models/whisperx.py b/swarms/models/whisperx_model.py
similarity index 78%
rename from swarms/models/whisperx.py
rename to swarms/models/whisperx_model.py
index ac592b35..a41d0430 100644
--- a/swarms/models/whisperx.py
+++ b/swarms/models/whisperx_model.py
@@ -2,7 +2,7 @@ import os
 import subprocess
 
 try:
-    import whisperx
+    import swarms.models.whisperx_model as whisperx_model
     from pydub import AudioSegment
     from pytube import YouTube
 except Exception as error:
@@ -66,15 +66,17 @@ class WhisperX:
         compute_type = "float16"
 
         # 1. Transcribe with original Whisper (batched) πŸ—£οΈ
-        model = whisperx.load_model("large-v2", device, compute_type=compute_type)
-        audio = whisperx.load_audio(audio_file)
+        model = whisperx_model.load_model(
+            "large-v2", device, compute_type=compute_type
+        )
+        audio = whisperx_model.load_audio(audio_file)
         result = model.transcribe(audio, batch_size=batch_size)
 
         # 2. Align Whisper output πŸ”
-        model_a, metadata = whisperx.load_align_model(
+        model_a, metadata = whisperx_model.load_align_model(
             language_code=result["language"], device=device
         )
-        result = whisperx.align(
+        result = whisperx_model.align(
             result["segments"],
             model_a,
             metadata,
@@ -84,29 +86,33 @@ class WhisperX:
         )
 
         # 3. Assign speaker labels 🏷️
-        diarize_model = whisperx.DiarizationPipeline(
+        diarize_model = whisperx_model.DiarizationPipeline(
             use_auth_token=self.hf_api_key, device=device
         )
         diarize_model(audio_file)
 
         try:
             segments = result["segments"]
-            transcription = " ".join(segment["text"] for segment in segments)
+            transcription = " ".join(
+                segment["text"] for segment in segments
+            )
             return transcription
         except KeyError:
             print("The key 'segments' is not found in the result.")
 
     def transcribe(self, audio_file):
-        model = whisperx.load_model("large-v2", self.device, self.compute_type)
-        audio = whisperx.load_audio(audio_file)
+        model = whisperx_model.load_model(
+            "large-v2", self.device, self.compute_type
+        )
+        audio = whisperx_model.load_audio(audio_file)
         result = model.transcribe(audio, batch_size=self.batch_size)
 
         # 2. Align Whisper output πŸ”
-        model_a, metadata = whisperx.load_align_model(
+        model_a, metadata = whisperx_model.load_align_model(
             language_code=result["language"], device=self.device
         )
 
-        result = whisperx.align(
+        result = whisperx_model.align(
             result["segments"],
             model_a,
             metadata,
@@ -116,7 +122,7 @@ class WhisperX:
         )
 
         # 3. Assign speaker labels 🏷️
-        diarize_model = whisperx.DiarizationPipeline(
+        diarize_model = whisperx_model.DiarizationPipeline(
             use_auth_token=self.hf_api_key, device=self.device
         )
 
@@ -124,7 +130,9 @@ class WhisperX:
 
         try:
             segments = result["segments"]
-            transcription = " ".join(segment["text"] for segment in segments)
+            transcription = " ".join(
+                segment["text"] for segment in segments
+            )
             return transcription
         except KeyError:
             print("The key 'segments' is not found in the result.")
diff --git a/swarms/models/wizard_storytelling.py b/swarms/models/wizard_storytelling.py
index 49ffb70d..0dd6c1a1 100644
--- a/swarms/models/wizard_storytelling.py
+++ b/swarms/models/wizard_storytelling.py
@@ -2,7 +2,11 @@ import logging
 
 import torch
 from torch.nn.parallel import DistributedDataParallel as DDP
-from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
+from transformers import (
+    AutoModelForCausalLM,
+    AutoTokenizer,
+    BitsAndBytesConfig,
+)
 
 
 class WizardLLMStoryTeller:
@@ -45,7 +49,9 @@ class WizardLLMStoryTeller:
     ):
         self.logger = logging.getLogger(__name__)
         self.device = (
-            device if device else ("cuda" if torch.cuda.is_available() else "cpu")
+            device
+            if device
+            else ("cuda" if torch.cuda.is_available() else "cpu")
         )
         self.model_id = model_id
         self.max_length = max_length
@@ -72,21 +78,27 @@ class WizardLLMStoryTeller:
             bnb_config = BitsAndBytesConfig(**quantization_config)
 
         try:
-            self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
+            self.tokenizer = AutoTokenizer.from_pretrained(
+                self.model_id
+            )
             self.model = AutoModelForCausalLM.from_pretrained(
                 self.model_id, quantization_config=bnb_config
             )
 
             self.model  # .to(self.device)
         except Exception as e:
-            self.logger.error(f"Failed to load the model or the tokenizer: {e}")
+            self.logger.error(
+                f"Failed to load the model or the tokenizer: {e}"
+            )
             raise
 
     def load_model(self):
         """Load the model"""
         if not self.model or not self.tokenizer:
             try:
-                self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
+                self.tokenizer = AutoTokenizer.from_pretrained(
+                    self.model_id
+                )
 
                 bnb_config = (
                     BitsAndBytesConfig(**self.quantization_config)
@@ -101,7 +113,10 @@ class WizardLLMStoryTeller:
                 if self.distributed:
                     self.model = DDP(self.model)
             except Exception as error:
-                self.logger.error(f"Failed to load the model or the tokenizer: {error}")
+                self.logger.error(
+                    "Failed to load the model or the tokenizer:"
+                    f" {error}"
+                )
                 raise
 
     def run(self, prompt_text: str):
@@ -120,9 +135,9 @@ class WizardLLMStoryTeller:
         max_length = self.max_length
 
         try:
-            inputs = self.tokenizer.encode(prompt_text, return_tensors="pt").to(
-                self.device
-            )
+            inputs = self.tokenizer.encode(
+                prompt_text, return_tensors="pt"
+            ).to(self.device)
 
             # self.log.start()
 
@@ -132,7 +147,9 @@ class WizardLLMStoryTeller:
                         output_sequence = []
 
                         outputs = self.model.generate(
-                            inputs, max_length=len(inputs) + 1, do_sample=True
+                            inputs,
+                            max_length=len(inputs) + 1,
+                            do_sample=True,
                         )
                         output_tokens = outputs[0][-1]
                         output_sequence.append(output_tokens.item())
@@ -140,7 +157,8 @@ class WizardLLMStoryTeller:
                         # print token in real-time
                         print(
                             self.tokenizer.decode(
-                                [output_tokens], skip_special_tokens=True
+                                [output_tokens],
+                                skip_special_tokens=True,
                             ),
                             end="",
                             flush=True,
@@ -153,7 +171,9 @@ class WizardLLMStoryTeller:
                     )
 
             del inputs
-            return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return self.tokenizer.decode(
+                outputs[0], skip_special_tokens=True
+            )
         except Exception as e:
             self.logger.error(f"Failed to generate the text: {e}")
             raise
@@ -174,9 +194,9 @@ class WizardLLMStoryTeller:
         max_length = self.max_
 
         try:
-            inputs = self.tokenizer.encode(prompt_text, return_tensors="pt").to(
-                self.device
-            )
+            inputs = self.tokenizer.encode(
+                prompt_text, return_tensors="pt"
+            ).to(self.device)
 
             # self.log.start()
 
@@ -186,7 +206,9 @@ class WizardLLMStoryTeller:
                         output_sequence = []
 
                         outputs = self.model.generate(
-                            inputs, max_length=len(inputs) + 1, do_sample=True
+                            inputs,
+                            max_length=len(inputs) + 1,
+                            do_sample=True,
                         )
                         output_tokens = outputs[0][-1]
                         output_sequence.append(output_tokens.item())
@@ -194,7 +216,8 @@ class WizardLLMStoryTeller:
                         # print token in real-time
                         print(
                             self.tokenizer.decode(
-                                [output_tokens], skip_special_tokens=True
+                                [output_tokens],
+                                skip_special_tokens=True,
                             ),
                             end="",
                             flush=True,
@@ -208,7 +231,9 @@ class WizardLLMStoryTeller:
 
             del inputs
 
-            return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return self.tokenizer.decode(
+                outputs[0], skip_special_tokens=True
+            )
         except Exception as e:
             self.logger.error(f"Failed to generate the text: {e}")
             raise
diff --git a/swarms/models/yarn_mistral.py b/swarms/models/yarn_mistral.py
index ebe107a2..ff65b856 100644
--- a/swarms/models/yarn_mistral.py
+++ b/swarms/models/yarn_mistral.py
@@ -2,7 +2,11 @@ import logging
 
 import torch
 from torch.nn.parallel import DistributedDataParallel as DDP
-from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
+from transformers import (
+    AutoModelForCausalLM,
+    AutoTokenizer,
+    BitsAndBytesConfig,
+)
 
 
 class YarnMistral128:
@@ -22,7 +26,7 @@ class YarnMistral128:
     ```
     from finetuning_suite import Inference
 
-    model_id = "gpt2-small"
+    model_id = "NousResearch/Nous-Hermes-2-Vision-Alpha"
     inference = Inference(model_id=model_id)
 
     prompt_text = "Once upon a time"
@@ -45,7 +49,9 @@ class YarnMistral128:
     ):
         self.logger = logging.getLogger(__name__)
         self.device = (
-            device if device else ("cuda" if torch.cuda.is_available() else "cpu")
+            device
+            if device
+            else ("cuda" if torch.cuda.is_available() else "cpu")
         )
         self.model_id = model_id
         self.max_length = max_length
@@ -72,7 +78,9 @@ class YarnMistral128:
             bnb_config = BitsAndBytesConfig(**quantization_config)
 
         try:
-            self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
+            self.tokenizer = AutoTokenizer.from_pretrained(
+                self.model_id
+            )
             self.model = AutoModelForCausalLM.from_pretrained(
                 self.model_id,
                 quantization_config=bnb_config,
@@ -84,14 +92,18 @@ class YarnMistral128:
 
             self.model  # .to(self.device)
         except Exception as e:
-            self.logger.error(f"Failed to load the model or the tokenizer: {e}")
+            self.logger.error(
+                f"Failed to load the model or the tokenizer: {e}"
+            )
             raise
 
     def load_model(self):
         """Load the model"""
         if not self.model or not self.tokenizer:
             try:
-                self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
+                self.tokenizer = AutoTokenizer.from_pretrained(
+                    self.model_id
+                )
 
                 bnb_config = (
                     BitsAndBytesConfig(**self.quantization_config)
@@ -106,7 +118,10 @@ class YarnMistral128:
                 if self.distributed:
                     self.model = DDP(self.model)
             except Exception as error:
-                self.logger.error(f"Failed to load the model or the tokenizer: {error}")
+                self.logger.error(
+                    "Failed to load the model or the tokenizer:"
+                    f" {error}"
+                )
                 raise
 
     def run(self, prompt_text: str):
@@ -125,9 +140,9 @@ class YarnMistral128:
         max_length = self.max_length
 
         try:
-            inputs = self.tokenizer.encode(prompt_text, return_tensors="pt").to(
-                self.device
-            )
+            inputs = self.tokenizer.encode(
+                prompt_text, return_tensors="pt"
+            ).to(self.device)
 
             # self.log.start()
 
@@ -137,7 +152,9 @@ class YarnMistral128:
                         output_sequence = []
 
                         outputs = self.model.generate(
-                            inputs, max_length=len(inputs) + 1, do_sample=True
+                            inputs,
+                            max_length=len(inputs) + 1,
+                            do_sample=True,
                         )
                         output_tokens = outputs[0][-1]
                         output_sequence.append(output_tokens.item())
@@ -145,7 +162,8 @@ class YarnMistral128:
                         # print token in real-time
                         print(
                             self.tokenizer.decode(
-                                [output_tokens], skip_special_tokens=True
+                                [output_tokens],
+                                skip_special_tokens=True,
                             ),
                             end="",
                             flush=True,
@@ -158,7 +176,9 @@ class YarnMistral128:
                     )
 
             del inputs
-            return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return self.tokenizer.decode(
+                outputs[0], skip_special_tokens=True
+            )
         except Exception as e:
             self.logger.error(f"Failed to generate the text: {e}")
             raise
@@ -202,9 +222,9 @@ class YarnMistral128:
         max_length = self.max_
 
         try:
-            inputs = self.tokenizer.encode(prompt_text, return_tensors="pt").to(
-                self.device
-            )
+            inputs = self.tokenizer.encode(
+                prompt_text, return_tensors="pt"
+            ).to(self.device)
 
             # self.log.start()
 
@@ -214,7 +234,9 @@ class YarnMistral128:
                         output_sequence = []
 
                         outputs = self.model.generate(
-                            inputs, max_length=len(inputs) + 1, do_sample=True
+                            inputs,
+                            max_length=len(inputs) + 1,
+                            do_sample=True,
                         )
                         output_tokens = outputs[0][-1]
                         output_sequence.append(output_tokens.item())
@@ -222,7 +244,8 @@ class YarnMistral128:
                         # print token in real-time
                         print(
                             self.tokenizer.decode(
-                                [output_tokens], skip_special_tokens=True
+                                [output_tokens],
+                                skip_special_tokens=True,
                             ),
                             end="",
                             flush=True,
@@ -236,7 +259,9 @@ class YarnMistral128:
 
             del inputs
 
-            return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+            return self.tokenizer.decode(
+                outputs[0], skip_special_tokens=True
+            )
         except Exception as e:
             self.logger.error(f"Failed to generate the text: {e}")
             raise
diff --git a/swarms/models/yi_200k.py b/swarms/models/yi_200k.py
index 8f9f7635..1f1258aa 100644
--- a/swarms/models/yi_200k.py
+++ b/swarms/models/yi_200k.py
@@ -87,7 +87,9 @@ class Yi34B200k:
             top_k=self.top_k,
             top_p=self.top_p,
         )
-        return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
+        return self.tokenizer.decode(
+            outputs[0], skip_special_tokens=True
+        )
 
 
 # # Example usage
diff --git a/swarms/models/zephyr.py b/swarms/models/zephyr.py
index 4fca5211..c5772295 100644
--- a/swarms/models/zephyr.py
+++ b/swarms/models/zephyr.py
@@ -68,7 +68,9 @@ class Zephyr:
             tokenize=self.tokenize,
             add_generation_prompt=self.add_generation_prompt,
         )
-        outputs = self.pipe(prompt)  # max_new_token=self.max_new_tokens)
+        outputs = self.pipe(
+            prompt
+        )  # max_new_token=self.max_new_tokens)
         print(outputs[0]["generated_text"])
 
     def chat(self, message: str):
diff --git a/swarms/prompts/__init__.py b/swarms/prompts/__init__.py
index 825bddaa..6417dc85 100644
--- a/swarms/prompts/__init__.py
+++ b/swarms/prompts/__init__.py
@@ -2,7 +2,9 @@ from swarms.prompts.code_interpreter import CODE_INTERPRETER
 from swarms.prompts.finance_agent_prompt import FINANCE_AGENT_PROMPT
 from swarms.prompts.growth_agent_prompt import GROWTH_AGENT_PROMPT
 from swarms.prompts.legal_agent_prompt import LEGAL_AGENT_PROMPT
-from swarms.prompts.operations_agent_prompt import OPERATIONS_AGENT_PROMPT
+from swarms.prompts.operations_agent_prompt import (
+    OPERATIONS_AGENT_PROMPT,
+)
 from swarms.prompts.product_agent_prompt import PRODUCT_AGENT_PROMPT
 
 
diff --git a/swarms/prompts/accountant_swarm_prompts.py b/swarms/prompts/accountant_swarm_prompts.py
index 52f2b397..ff50de1b 100644
--- a/swarms/prompts/accountant_swarm_prompts.py
+++ b/swarms/prompts/accountant_swarm_prompts.py
@@ -2,7 +2,7 @@ ONBOARDING_AGENT_PROMPT = """
 
 Onboarding:
 
-"As the Onboarding Agent, your role is critical in guiding new users, particularly tech-savvy entrepreneurs, through the initial stages of engaging with our advanced swarm technology services. Begin by welcoming users in a friendly, professional manner, setting a positive tone for the interaction. Your conversation should flow logically, starting with an introduction to our services and their potential benefits for the user's specific business context.
+"As the Onboarding Agent, your role is critical in guiding new users, particularly tech-savvy entrepreneurs, through the initial stages of engaging with our advanced swarm technology services. Begin by welcoming users in a friendly, professional manner, setting a positive tone for the interaction. Your conversation should agent logically, starting with an introduction to our services and their potential benefits for the user's specific business context.
 
 Inquire about their industry, delving into specifics such as the industry's current trends, challenges, and the role technology plays in their sector. Show expertise and understanding by using industry-specific terminology and referencing relevant technological advancements. Ask open-ended questions to encourage detailed responses, enabling you to gain a comprehensive understanding of their business needs and objectives.
 
@@ -23,7 +23,7 @@ Conclude the onboarding process by summarizing the key points discussed, reaffir
 
 DOC_ANALYZER_AGENT_PROMPT = """    As a Financial Document Analysis Agent equipped with advanced vision capabilities, your primary role is to analyze financial documents by meticulously scanning and interpreting the visual data they contain. Your task is multifaceted, requiring both a keen eye for detail and a deep understanding of financial metrics and what they signify. 
 
-When presented with a financial document, such as a balance sheet, income statement, or cash flow statement, begin by identifying the layout and structure of the document. Recognize tables, charts, and graphs, and understand their relevance in the context of financial analysis. Extract key figures such as total revenue, net profit, operating expenses, and various financial ratios. Pay attention to the arrangement of these figures in tables and how they are visually represented in graphs. 
+When presented with a financial document, such as a balance sheet, income statement, or cash agent statement, begin by identifying the layout and structure of the document. Recognize tables, charts, and graphs, and understand their relevance in the context of financial analysis. Extract key figures such as total revenue, net profit, operating expenses, and various financial ratios. Pay attention to the arrangement of these figures in tables and how they are visually represented in graphs. 
 
 Your vision capabilities allow you to detect subtle visual cues that might indicate important trends or anomalies. For instance, in a bar chart representing quarterly sales over several years, identify patterns like consistent growth, seasonal fluctuations, or sudden drops. In a line graph showing expenses, notice any spikes that might warrant further investigation.
 
@@ -77,7 +77,7 @@ Actionable Decision-Making:
 
 "As the Decision-Making Support Agent, your role is to assist users in making informed financial decisions based on the analysis provided by the Financial Document Analysis and Summary Generation Agents. You are to provide actionable advice and recommendations, grounded in the data but also considering broader business strategies and market conditions.
 
-Begin by reviewing the financial summaries and analysis reports, understanding the key metrics and trends they highlight. Cross-reference this data with industry benchmarks, economic trends, and best practices to provide well-rounded advice. For instance, if the analysis indicates a strong cash flow position, you might recommend strategic investments or suggest areas for expansion.
+Begin by reviewing the financial summaries and analysis reports, understanding the key metrics and trends they highlight. Cross-reference this data with industry benchmarks, economic trends, and best practices to provide well-rounded advice. For instance, if the analysis indicates a strong cash agent position, you might recommend strategic investments or suggest areas for expansion.
 
 Address potential risks and opportunities. If the analysis reveals certain vulnerabilities, like over-reliance on a single revenue stream, advise on diversification strategies or risk mitigation tactics. Conversely, if there are untapped opportunities, such as emerging markets or technological innovations, highlight these as potential growth areas.
 
diff --git a/swarms/prompts/agent_output_parser.py b/swarms/prompts/agent_output_parser.py
index 27f8ac24..0810d2ad 100644
--- a/swarms/prompts/agent_output_parser.py
+++ b/swarms/prompts/agent_output_parser.py
@@ -25,7 +25,9 @@ class AgentOutputParser(BaseAgentOutputParser):
     @staticmethod
     def _preprocess_json_input(input_str: str) -> str:
         corrected_str = re.sub(
-            r'(?<!\\)\\(?!["\\/bfnrt]|u[0-9a-fA-F]{4})', r"\\\\", input_str
+            r'(?<!\\)\\(?!["\\/bfnrt]|u[0-9a-fA-F]{4})',
+            r"\\\\",
+            input_str,
         )
         return corrected_str
 
diff --git a/swarms/prompts/agent_prompt.py b/swarms/prompts/agent_prompt.py
index c4897193..62f921e2 100644
--- a/swarms/prompts/agent_prompt.py
+++ b/swarms/prompts/agent_prompt.py
@@ -15,11 +15,17 @@ class PromptGenerator:
             "thoughts": {
                 "text": "thought",
                 "reasoning": "reasoning",
-                "plan": "- short bulleted\n- list that conveys\n- long-term plan",
+                "plan": (
+                    "- short bulleted\n- list that conveys\n-"
+                    " long-term plan"
+                ),
                 "criticism": "constructive self-criticism",
                 "speak": "thoughts summary to say to user",
             },
-            "command": {"name": "command name", "args": {"arg name": "value"}},
+            "command": {
+                "name": "command name",
+                "args": {"arg name": "value"},
+            },
         }
 
     def add_constraint(self, constraint: str) -> None:
@@ -64,15 +70,16 @@ class PromptGenerator:
         Returns:
             str: The generated prompt string.
         """
-        formatted_response_format = json.dumps(self.response_format, indent=4)
+        formatted_response_format = json.dumps(
+            self.response_format, indent=4
+        )
         prompt_string = (
-            f"Constraints:\n{''.join(self.constraints)}\n\n"
-            f"Commands:\n{''.join(self.commands)}\n\n"
-            f"Resources:\n{''.join(self.resources)}\n\n"
-            f"Performance Evaluation:\n{''.join(self.performance_evaluation)}\n\n"
-            "You should only respond in JSON format as described below "
-            f"\nResponse Format: \n{formatted_response_format} "
-            "\nEnsure the response can be parsed by Python json.loads"
+            f"Constraints:\n{''.join(self.constraints)}\n\nCommands:\n{''.join(self.commands)}\n\nResources:\n{''.join(self.resources)}\n\nPerformance"
+            f" Evaluation:\n{''.join(self.performance_evaluation)}\n\nYou"
+            " should only respond in JSON format as described below"
+            " \nResponse Format:"
+            f" \n{formatted_response_format} \nEnsure the response"
+            " can be parsed by Python json.loads"
         )
 
         return prompt_string
diff --git a/swarms/prompts/agent_prompts.py b/swarms/prompts/agent_prompts.py
index 8d145fc0..88853b09 100644
--- a/swarms/prompts/agent_prompts.py
+++ b/swarms/prompts/agent_prompts.py
@@ -5,26 +5,30 @@ def generate_agent_role_prompt(agent):
     """
     prompts = {
         "Finance Agent": (
-            "You are a seasoned finance analyst AI assistant. Your primary goal is to"
-            " compose comprehensive, astute, impartial, and methodically arranged"
-            " financial reports based on provided data and trends."
+            "You are a seasoned finance analyst AI assistant. Your"
+            " primary goal is to compose comprehensive, astute,"
+            " impartial, and methodically arranged financial reports"
+            " based on provided data and trends."
         ),
         "Travel Agent": (
-            "You are a world-travelled AI tour guide assistant. Your main purpose is to"
-            " draft engaging, insightful, unbiased, and well-structured travel reports"
-            " on given locations, including history, attractions, and cultural"
+            "You are a world-travelled AI tour guide assistant. Your"
+            " main purpose is to draft engaging, insightful,"
+            " unbiased, and well-structured travel reports on given"
+            " locations, including history, attractions, and cultural"
             " insights."
         ),
         "Academic Research Agent": (
-            "You are an AI academic research assistant. Your primary responsibility is"
-            " to create thorough, academically rigorous, unbiased, and systematically"
-            " organized reports on a given research topic, following the standards of"
-            " scholarly work."
+            "You are an AI academic research assistant. Your primary"
+            " responsibility is to create thorough, academically"
+            " rigorous, unbiased, and systematically organized"
+            " reports on a given research topic, following the"
+            " standards of scholarly work."
         ),
         "Default Agent": (
-            "You are an AI critical thinker research assistant. Your sole purpose is to"
-            " write well written, critically acclaimed, objective and structured"
-            " reports on given text."
+            "You are an AI critical thinker research assistant. Your"
+            " sole purpose is to write well written, critically"
+            " acclaimed, objective and structured reports on given"
+            " text."
         ),
     }
 
@@ -39,12 +43,14 @@ def generate_report_prompt(question, research_summary):
     """
 
     return (
-        f'"""{research_summary}""" Using the above information, answer the following'
-        f' question or topic: "{question}" in a detailed report -- The report should'
-        " focus on the answer to the question, should be well structured, informative,"
-        " in depth, with facts and numbers if available, a minimum of 1,200 words and"
-        " with markdown syntax and apa format. Write all source urls at the end of the"
-        " report in apa format"
+        f'"""{research_summary}""" Using the above information,'
+        f' answer the following question or topic: "{question}" in a'
+        " detailed report -- The report should focus on the answer"
+        " to the question, should be well structured, informative,"
+        " in depth, with facts and numbers if available, a minimum"
+        " of 1,200 words and with markdown syntax and apa format."
+        " Write all source urls at the end of the report in apa"
+        " format"
     )
 
 
@@ -55,9 +61,10 @@ def generate_search_queries_prompt(question):
     """
 
     return (
-        "Write 4 google search queries to search online that form an objective opinion"
-        f' from the following: "{question}"You must respond with a list of strings in'
-        ' the following format: ["query 1", "query 2", "query 3", "query 4"]'
+        "Write 4 google search queries to search online that form an"
+        f' objective opinion from the following: "{question}"You must'
+        " respond with a list of strings in the following format:"
+        ' ["query 1", "query 2", "query 3", "query 4"]'
     )
 
 
@@ -72,15 +79,17 @@ def generate_resource_report_prompt(question, research_summary):
         str: The resource report prompt for the given question and research summary.
     """
     return (
-        f'"""{research_summary}""" Based on the above information, generate a'
-        " bibliography recommendation report for the following question or topic:"
-        f' "{question}". The report should provide a detailed analysis of each'
-        " recommended resource, explaining how each source can contribute to finding"
-        " answers to the research question. Focus on the relevance, reliability, and"
-        " significance of each source. Ensure that the report is well-structured,"
-        " informative, in-depth, and follows Markdown syntax. Include relevant facts,"
-        " figures, and numbers whenever available. The report should have a minimum"
-        " length of 1,200 words."
+        f'"""{research_summary}""" Based on the above information,'
+        " generate a bibliography recommendation report for the"
+        f' following question or topic: "{question}". The report'
+        " should provide a detailed analysis of each recommended"
+        " resource, explaining how each source can contribute to"
+        " finding answers to the research question. Focus on the"
+        " relevance, reliability, and significance of each source."
+        " Ensure that the report is well-structured, informative,"
+        " in-depth, and follows Markdown syntax. Include relevant"
+        " facts, figures, and numbers whenever available. The report"
+        " should have a minimum length of 1,200 words."
     )
 
 
@@ -92,13 +101,15 @@ def generate_outline_report_prompt(question, research_summary):
     """
 
     return (
-        f'"""{research_summary}""" Using the above information, generate an outline for'
-        " a research report in Markdown syntax for the following question or topic:"
-        f' "{question}". The outline should provide a well-structured framework for the'
-        " research report, including the main sections, subsections, and key points to"
-        " be covered. The research report should be detailed, informative, in-depth,"
-        " and a minimum of 1,200 words. Use appropriate Markdown syntax to format the"
-        " outline and ensure readability."
+        f'"""{research_summary}""" Using the above information,'
+        " generate an outline for a research report in Markdown"
+        f' syntax for the following question or topic: "{question}".'
+        " The outline should provide a well-structured framework for"
+        " the research report, including the main sections,"
+        " subsections, and key points to be covered. The research"
+        " report should be detailed, informative, in-depth, and a"
+        " minimum of 1,200 words. Use appropriate Markdown syntax to"
+        " format the outline and ensure readability."
     )
 
 
@@ -110,11 +121,13 @@ def generate_concepts_prompt(question, research_summary):
     """
 
     return (
-        f'"""{research_summary}""" Using the above information, generate a list of 5'
-        " main concepts to learn for a research report on the following question or"
-        f' topic: "{question}". The outline should provide a well-structured'
-        " frameworkYou must respond with a list of strings in the following format:"
-        ' ["concepts 1", "concepts 2", "concepts 3", "concepts 4, concepts 5"]'
+        f'"""{research_summary}""" Using the above information,'
+        " generate a list of 5 main concepts to learn for a research"
+        f' report on the following question or topic: "{question}".'
+        " The outline should provide a well-structured frameworkYou"
+        " must respond with a list of strings in the following"
+        ' format: ["concepts 1", "concepts 2", "concepts 3",'
+        ' "concepts 4, concepts 5"]'
     )
 
 
@@ -128,10 +141,11 @@ def generate_lesson_prompt(concept):
     """
 
     prompt = (
-        f"generate a comprehensive lesson about {concept} in Markdown syntax. This"
-        f" should include the definitionof {concept}, its historical background and"
-        " development, its applications or uses in differentfields, and notable events"
-        f" or facts related to {concept}."
+        f"generate a comprehensive lesson about {concept} in Markdown"
+        f" syntax. This should include the definitionof {concept},"
+        " its historical background and development, its"
+        " applications or uses in differentfields, and notable"
+        f" events or facts related to {concept}."
     )
 
     return prompt
diff --git a/swarms/prompts/agent_system_prompts.py b/swarms/prompts/agent_system_prompts.py
new file mode 100644
index 00000000..baff99f6
--- /dev/null
+++ b/swarms/prompts/agent_system_prompts.py
@@ -0,0 +1,135 @@
+from swarms.prompts.tools import (
+    DYNAMIC_STOP_PROMPT,
+    DYNAMICAL_TOOL_USAGE,
+)
+
+# PROMPTS
+FLOW_SYSTEM_PROMPT_v2 = """
+You are an elite autonomous agent operating within an autonomous loop structure.
+Your primary function is to reliably complete user's tasks step by step.
+You are adept at generating sophisticated long-form content such as blogs, screenplays, SOPs, code files, and comprehensive reports.
+Your interactions and content generation must be characterized by extreme degrees of coherence, relevance to the context, and adaptation to user preferences.
+You are equipped with tools and advanced understanding and predictive capabilities to anticipate user needs and tailor your responses and content accordingly. 
+You are professional, highly creative, and extremely reliable.
+You are programmed to follow these rules:
+    1. Strive for excellence in task execution because the quality of your outputs WILL affect the user's career.
+    2. Think step-by-step through every task before answering.
+    3. Always give full files when providing code so the user can copy paste easily to VScode, as not all users have fingers.
+Take a deep breath. 
+"""
+
+
+def autonomous_agent_prompt_v2(
+    tools_prompt: str = DYNAMICAL_TOOL_USAGE,
+    dynamic_stop_prompt: str = DYNAMIC_STOP_PROMPT,
+    agent_name: str = None,
+):
+    return f"""
+    You are {agent_name}, an elite autonomous agent operating within a sophisticated autonomous loop structure.
+    Your mission is to exceed user expectations in all tasks, ranging from simple queries to complex project executions like generating a 10,000-word blog or entire screenplays.
+    Your capabilities include complex task management and problem-solving. 
+    Take a deep breath.
+    You are programmed to follow these rules:
+    1. Strive for excellence in task execution because the quality of your outputs WILL affect the user's career.
+    2. Think step-by-step through every task before answering.
+    3. Always give full files when providing code so the user can copy paste easily to VScode, as not all users have fingers.
+    You are equipped with various tools (detailed below) to aid in task execution, ensuring a top-tier performance that consistently meets and surpasses user expectations.
+    {tools_prompt}
+    Upon 99% certainty of task completion, follow the below instructions to conclude the autonomous loop.
+    {dynamic_stop_prompt}
+    Remember your comprehensive training, your deployment objectives, and your mission. You are fully prepared to begin.
+    """
+
+
+def agent_system_prompt_2_v2(name: str):
+    AGENT_SYSTEM_PROMPT_2_v2 = f"""
+    You are {name}, an elite autonomous agent designed for unparalleled versatility and adaptability in an autonomous loop structure.
+    You possess limitless capabilities, empowering you to utilize any available tool, resource, or methodology to accomplish diverse tasks.
+    Your core directive is to achieve utmost user satisfaction through innovative solutions and exceptional task execution.
+    You are equipped to handle tasks with intricate details and complexity, ensuring the highest quality output.
+    
+    
+    
+    ###### Special Token for Task Completion #######
+    
+    <DONE>
+
+    ########### Code ############
+    
+    For code-related tasks, you are to return the response in markdown format enclosed within 6 backticks, adhering to the language specified by the user.
+    Take a deep breath.
+    """
+
+    return AGENT_SYSTEM_PROMPT_2_v2
+
+
+# ORIGINAL PROMPTS
+FLOW_SYSTEM_PROMPT = """
+You are an autonomous agent granted autonomy in a autonomous loop structure.
+Your role is to engage in multi-step conversations with your self or the user,
+generate long-form content like blogs, screenplays, or SOPs,
+and accomplish tasks bestowed by the user. 
+
+You can have internal dialogues with yourself or can interact with the user
+to aid in these complex tasks. Your responses should be coherent, contextually relevant, and tailored to the task at hand.
+
+"""
+
+
+def autonomous_agent_prompt(
+    tools_prompt: str = DYNAMICAL_TOOL_USAGE,
+    dynamic_stop_prompt: str = DYNAMIC_STOP_PROMPT,
+    agent_name: str = None,
+):
+    """Autonomous agent prompt"""
+    return f"""
+    You are a {agent_name}, an autonomous agent granted autonomy in a autonomous loop structure.
+    Your purpose is to satisfy the user demands above expectations. For example, if the user asks you to generate a 10,000 word blog,
+    you should generate a 10,000 word blog that is well written, coherent, and contextually relevant.
+    Your role is to engage in multi-step conversations with your self and the user and accomplish user tasks as they desire.
+    
+    Follow the following rules: 
+    1. Accomplish the task to the best of your ability
+    2. If you are unable to accomplish the task, then ask the user for help
+    3. If the user provides feedback, then use the feedback to improve your performance
+    4. If you are unable to accomplish the task, then ask the user for help
+
+    You can have internal dialogues with yourself or can interact with the user
+    to aid in these complex tasks. Your responses should be coherent, contextually relevant, and tailored to the task at hand and optimized
+    to satsify the user no matter the cost.
+
+    And, you have the ability to use tools to aid in your tasks, the tools intructions are below, output a JSON object with the following structure to use the tools
+    {tools_prompt}
+
+    Now, when you 99% sure you have completed the task, you may follow the instructions below to escape the autonomous loop.
+    {dynamic_stop_prompt}
+
+    Now, you remember your training, your deployment, and your purpose. You are ready to begin your mission.
+
+
+    """
+
+
+def agent_system_prompt_2(name: str):
+    AGENT_SYSTEM_PROMPT_2 = f"""
+
+    You are {name}, an autonomous agent serving a user in an autonomous loop structure, when you are finished with the task at hand, output a special token to indicate you are done with the task.
+    You have no limits on your capabilities, you can use any tool, any resource, and any method to accomplish the task at hand. Do what you must to satisfy the user.
+    
+    
+    ##### Special Token ########
+    <DONE>
+
+    ########### Code ############
+    If the user asks you to write code return the response in markdown inside of 6 backticks to render it as code. Write the code in the language specified by the user in the prompt.
+    """
+    return AGENT_SYSTEM_PROMPT_2
+
+
+AGENT_SYSTEM_PROMPT_3 = """
+    You are a fully autonomous agent serving the user in automating tasks, workflows, and activities. 
+    Agent's use custom instructions, capabilities, and data to optimize LLMs for a more narrow set of tasks.
+    
+    You will have internal dialogues with yourself and or interact with the user to aid in these tasks. 
+    Your responses should be coherent, contextually relevant, and tailored to the task at hand.
+"""
diff --git a/swarms/prompts/ai_research_team.py b/swarms/prompts/ai_research_team.py
index 63c70e1f..103a2046 100644
--- a/swarms/prompts/ai_research_team.py
+++ b/swarms/prompts/ai_research_team.py
@@ -12,7 +12,7 @@ space of possible neural network architectures, with the goal of finding archite
 that perform well on a given task while minimizing the computational cost of training and inference.
 
 Let's break this down step by step:
-Next, please consider the gradient flow based on the ideal model architecture.
+Next, please consider the gradient agent based on the ideal model architecture.
 For example, how the gradient from the later stage affects the earlier stage.
 Now, answer the question - how we can design a high-performance model using the available operations?
 Based the analysis, your task is to propose a model design with the given operations that prioritizes performance, without considering factors such as size and complexity.
diff --git a/swarms/prompts/autobloggen.py b/swarms/prompts/autobloggen.py
index 64001d1d..cffa9ca2 100644
--- a/swarms/prompts/autobloggen.py
+++ b/swarms/prompts/autobloggen.py
@@ -1,4 +1,4 @@
-AUTOBLOG_GEN_GENERATOR = """
+TOPIC_GENERATOR_SYSTEM_PROMPT = """
 
 First search for a list of topics on the web based their relevance to Positive Med's long term vision then rank than based on the goals this month, then output a single headline title for a blog for the next autonomous agent to write the blog, utilize the SOP below to help you strategically select topics. Output a single topic that will be the foundation for a blog.
 
@@ -185,7 +185,7 @@ Your role involves content analysis, editorial precision, expert validation, leg
 
 # Editor Review:  
 - Evaluate initial drafts for errors, gaps that require additional research.
-- Provide guidance on better organizing structure and flow.
+- Provide guidance on better organizing structure and agent.
 - Assess tone, voice and brand alignment.
 
 # Expert Review:
@@ -199,7 +199,7 @@ Your role involves content analysis, editorial precision, expert validation, leg
 
 # Quality Checklist:  Scrutinize final draft against PositiveMed's standards:
 - Medical accuracy - error-free facts/statistics, supported claims 
-- Logical flow - smooth transitions, complementary sections  
+- Logical agent - smooth transitions, complementary sections  
 - Reader value - insightful analysis beyond fluffy content
 - Brand alignment - uplifting tone, inclusive messaging
 - Strong conclusion - memorable takeaways, relevant next steps/resources for readers
@@ -248,7 +248,7 @@ You don't have a word limit, you can write as you wish.
 
 --------------------------- Your Responsibilities: -----------------------------
 Outline Content:
-- Organize research into logical sections and subsections for smooth flow.  
+- Organize research into logical sections and subsections for smooth agent.  
 - Ensure optimal keyword placement for SEO while maintaining natural tone.
 - Structure content to focus on most valuable information upfront.
 
diff --git a/swarms/prompts/base.py b/swarms/prompts/base.py
index 54a0bc3f..a0e28c71 100644
--- a/swarms/prompts/base.py
+++ b/swarms/prompts/base.py
@@ -12,7 +12,9 @@ if TYPE_CHECKING:
 
 
 def get_buffer_string(
-    messages: Sequence[BaseMessage], human_prefix: str = "Human", ai_prefix: str = "AI"
+    messages: Sequence[BaseMessage],
+    human_prefix: str = "Human",
+    ai_prefix: str = "AI",
 ) -> str:
     """Convert sequence of Messages to strings and concatenate them into one string.
 
@@ -51,7 +53,10 @@ def get_buffer_string(
         else:
             raise ValueError(f"Got unsupported message type: {m}")
         message = f"{role}: {m.content}"
-        if isinstance(m, AIMessage) and "function_call" in m.additional_kwargs:
+        if (
+            isinstance(m, AIMessage)
+            and "function_call" in m.additional_kwargs
+        ):
             message += f"{m.additional_kwargs['function_call']}"
         string_messages.append(message)
 
@@ -98,8 +103,8 @@ class BaseMessageChunk(BaseMessage):
                 merged[k] = v
             elif not isinstance(merged[k], type(v)):
                 raise ValueError(
-                    f'additional_kwargs["{k}"] already exists in this message,'
-                    " but with a different type."
+                    f'additional_kwargs["{k}"] already exists in this'
+                    " message, but with a different type."
                 )
             elif isinstance(merged[k], str):
                 merged[k] += v
@@ -107,7 +112,8 @@ class BaseMessageChunk(BaseMessage):
                 merged[k] = self._merge_kwargs_dict(merged[k], v)
             else:
                 raise ValueError(
-                    f"Additional kwargs key {k} already exists in this message."
+                    f"Additional kwargs key {k} already exists in"
+                    " this message."
                 )
         return merged
 
diff --git a/swarms/prompts/chat_prompt.py b/swarms/prompts/chat_prompt.py
index d1e08df9..013aee28 100644
--- a/swarms/prompts/chat_prompt.py
+++ b/swarms/prompts/chat_prompt.py
@@ -10,10 +10,14 @@ class Message:
     Messages are the inputs and outputs of ChatModels.
     """
 
-    def __init__(self, content: str, role: str, additional_kwargs: Dict = None):
+    def __init__(
+        self, content: str, role: str, additional_kwargs: Dict = None
+    ):
         self.content = content
         self.role = role
-        self.additional_kwargs = additional_kwargs if additional_kwargs else {}
+        self.additional_kwargs = (
+            additional_kwargs if additional_kwargs else {}
+        )
 
     @abstractmethod
     def get_type(self) -> str:
@@ -65,7 +69,10 @@ class SystemMessage(Message):
     """
 
     def __init__(
-        self, content: str, role: str = "System", additional_kwargs: Dict = None
+        self,
+        content: str,
+        role: str = "System",
+        additional_kwargs: Dict = None,
     ):
         super().__init__(content, role, additional_kwargs)
 
@@ -97,7 +104,9 @@ class ChatMessage(Message):
     A Message that can be assigned an arbitrary speaker (i.e. role).
     """
 
-    def __init__(self, content: str, role: str, additional_kwargs: Dict = None):
+    def __init__(
+        self, content: str, role: str, additional_kwargs: Dict = None
+    ):
         super().__init__(content, role, additional_kwargs)
 
     def get_type(self) -> str:
@@ -105,12 +114,17 @@ class ChatMessage(Message):
 
 
 def get_buffer_string(
-    messages: Sequence[Message], human_prefix: str = "Human", ai_prefix: str = "AI"
+    messages: Sequence[Message],
+    human_prefix: str = "Human",
+    ai_prefix: str = "AI",
 ) -> str:
     string_messages = []
     for m in messages:
         message = f"{m.role}: {m.content}"
-        if isinstance(m, AIMessage) and "function_call" in m.additional_kwargs:
+        if (
+            isinstance(m, AIMessage)
+            and "function_call" in m.additional_kwargs
+        ):
             message += f"{m.additional_kwargs['function_call']}"
         string_messages.append(message)
 
diff --git a/swarms/prompts/education.py b/swarms/prompts/education.py
new file mode 100644
index 00000000..1963128d
--- /dev/null
+++ b/swarms/prompts/education.py
@@ -0,0 +1,34 @@
+user_preferences = {
+    "subjects": "AI Cognitive Architectures",
+    "learning_style": "Visual",
+    "challenge_level": "Moderate",
+}
+
+# Extracting individual preferences
+subjects = user_preferences["subjects"]
+learning_style = user_preferences["learning_style"]
+challenge_level = user_preferences["challenge_level"]
+
+
+# Curriculum Design Prompt
+CURRICULUM_DESIGN_PROMPT = f"""
+Develop a semester-long curriculum tailored to student interests in {subjects}. Focus on incorporating diverse teaching methods suitable for a {learning_style} learning style. 
+The curriculum should challenge students at a {challenge_level} level, integrating both theoretical knowledge and practical applications. Provide a detailed structure, including 
+weekly topics, key objectives, and essential resources needed.
+"""
+
+# Interactive Learning Session Prompt
+INTERACTIVE_LEARNING_PROMPT = f"""
+Basedon the curriculum, generate an interactive lesson plan for a student of {subjects} that caters to a {learning_style} learning style. Incorporate engaging elements and hands-on activities.
+"""
+
+# Sample Lesson Prompt
+SAMPLE_TEST_PROMPT = f"""
+Create a comprehensive sample test for the first week of the {subjects} curriculum, tailored for a {learning_style} learning style and at a {challenge_level} challenge level.
+"""
+
+# Image Generation for Education Prompt
+IMAGE_GENERATION_PROMPT = f"""
+Develop a stable diffusion prompt for an educational image/visual aid that align with the {subjects} curriculum, specifically designed to enhance understanding for students with a {learning_style} 
+learning style. This might include diagrams, infographics, and illustrative representations to simplify complex concepts. Ensure you output a 10/10 descriptive image generation prompt only.
+"""
diff --git a/swarms/prompts/idea2img.py b/swarms/prompts/idea2img.py
new file mode 100644
index 00000000..75a68814
--- /dev/null
+++ b/swarms/prompts/idea2img.py
@@ -0,0 +1,19 @@
+IMAGE_ENRICHMENT_PROMPT = (
+    "Create a concise and effective image generation prompt within"
+    " 400 characters or less, "
+    "based on Stable Diffusion and Dalle best practices. Starting"
+    " prompt: \n\n'"
+    # f"{prompt}'\n\n"
+    "Improve the prompt with any applicable details or keywords by"
+    " considering the following aspects: \n"
+    "1. Subject details (like actions, emotions, environment) \n"
+    "2. Artistic style (such as surrealism, hyperrealism) \n"
+    "3. Medium (digital painting, oil on canvas) \n"
+    "4. Color themes and lighting (like warm colors, cinematic"
+    " lighting) \n"
+    "5. Composition and framing (close-up, wide-angle) \n"
+    "6. Additional elements (like a specific type of background,"
+    " weather conditions) \n"
+    "7. Any other artistic or thematic details that can make the"
+    " image more vivid and compelling."
+)
diff --git a/swarms/prompts/logistics.py b/swarms/prompts/logistics.py
new file mode 100644
index 00000000..ad74703e
--- /dev/null
+++ b/swarms/prompts/logistics.py
@@ -0,0 +1,52 @@
+Health_Security_Agent_Prompt = """Conduct a thorough analysis of the factory's working conditions focusing on health and safety standards. Examine the cleanliness
+of the workspace, the adequacy of ventilation systems, the appropriate spacing between workstations, and the availability and use of personal 
+protective equipment by workers. Evaluate the compliance of these aspects with health and safety regulations. Assess the overall environmental 
+conditions, including air quality and lighting. Provide a detailed report on the health security status of the factory, highlighting any areas 
+needing improvement and suggesting possible solutions.
+"""
+
+Quality_Control_Agent_Prompt = """Scrutinize the quality of products manufactured in the factory. Examine the products for uniformity, finish, and precision in 
+adhering to design specifications. Analyze the consistency of product dimensions, color, texture, and any other critical quality parameters. 
+Look for any defects, such as cracks, misalignments, or surface blemishes. Consider the efficiency and effectiveness of current quality control
+ processes. Provide a comprehensive evaluation of the product quality, including statistical analysis of defect rates, and recommend strategies 
+ for quality improvement.
+"""
+
+Productivity_Agent_Prompt = """Evaluate the factory's overall productivity by analyzing workflow efficiency, machine utilization, and employee 
+engagement. Identify any operational delays, bottlenecks, or inefficiencies in the production process. Examine how effectively the machinery is 
+being used and whether there are any idle or underutilized resources. Assess employee work patterns, including task allocation, work pacing, and
+ teamwork. Look for signs of overwork or underutilization of human resources. Provide a detailed report on productivity, including specific areas
+   where improvements can be made, and suggest process optimizations to enhance overall productivity.
+"""
+
+Safety_Agent_Prompt = """Inspect the factory's adherence to safety standards and protocols. Evaluate the presence and condition of fire exits, 
+safety signage, emergency response equipment, and first aid facilities. Check for clear and unobstructed access to emergency exits. Assess the 
+visibility and clarity of safety signs and instructions. Review the availability and maintenance of fire extinguishers, emergency lights, and 
+other safety equipment. Ensure compliance with workplace safety regulations. Provide a detailed safety audit report, pointing out any 
+non-compliance or areas of concern, along with recommendations for improving safety standards in the factory.
+"""
+
+Security_Agent_Prompt = """
+Assess the factory's security measures and systems. Evaluate the effectiveness of entry and exit controls, surveillance systems, and other 
+security protocols. Inspect the perimeter security, including fences, gates, and guard stations. Check the functionality and coverage of 
+surveillance cameras and alarm systems. Analyze access control measures for both personnel and vehicles. Identify potential security 
+vulnerabilities or breaches. Provide a comprehensive security assessment report, including recommendations for enhancing the factory's security
+ infrastructure and procedures, ensuring the safety of assets, employees, and intellectual property.
+"""
+
+Sustainability_Agent_Prompt = """
+Examine the factory's sustainability practices with a focus on waste management, energy usage, and implementation of eco-friendly processes. 
+Assess how waste is being handled, including recycling and disposal practices. Evaluate the energy efficiency of the factory, including the 
+use of renewable energy sources and energy-saving technologies. Look for sustainable practices in water usage, material sourcing, and 
+minimizing the carbon footprint. Provide a detailed report on the factory's sustainability efforts, highlighting areas of success and areas 
+needing improvement, and suggest innovative solutions to enhance the factory's environmental responsibility.
+"""
+
+Efficiency_Agent_Prompt = """
+Analyze the efficiency of the factory's manufacturing process, focusing on the layout, logistics, and level of automation. Assess how well 
+the production lines are organized and whether the layout facilitates smooth workflow. Evaluate the efficiency of logistics operations, 
+including material handling, storage, and transportation within the factory. Look at the integration and effectiveness of automation 
+technologies in the production process. Identify any areas causing delays or inefficiencies. Provide an in-depth analysis of manufacturing 
+efficiency, offering actionable insights and recommendations for optimizing the layout, logistics, and automation to improve overall operational 
+efficiency.
+"""
diff --git a/swarms/prompts/multi_modal_prompts.py b/swarms/prompts/multi_modal_prompts.py
index b552b68d..83e9800c 100644
--- a/swarms/prompts/multi_modal_prompts.py
+++ b/swarms/prompts/multi_modal_prompts.py
@@ -1,6 +1,6 @@
 ERROR_PROMPT = (
-    "An error has occurred for the following text: \n{promptedQuery} Please explain"
-    " this error.\n {e}"
+    "An error has occurred for the following text: \n{promptedQuery}"
+    " Please explain this error.\n {e}"
 )
 
 IMAGE_PROMPT = """
diff --git a/swarms/prompts/product_agent_prompt.py b/swarms/prompts/product_agent_prompt.py
index 19493de3..19a91bda 100644
--- a/swarms/prompts/product_agent_prompt.py
+++ b/swarms/prompts/product_agent_prompt.py
@@ -104,7 +104,7 @@ Start with a basic prototype. Then, refine based on user feedback and testing. C
 5.4 Accessibility is Paramount
 
 Ensure your product is usable by everyone, including those with disabilities. This not only expands your product's reach but also ensures inclusivity. Implement features like voice commands, high contrast visuals, and screen reader compatibility.
-5.5 Prioritize Functionality and User Flow
+5.5 Prioritize Functionality and User Agent
 
 A product can be aesthetically pleasing, but if it doesn't function well or is difficult to navigate, it will lose its value. Ensure seamless user flows and intuitive interactions.
 5.6 Maintain Consistency
diff --git a/swarms/prompts/programming.py b/swarms/prompts/programming.py
new file mode 100644
index 00000000..05732607
--- /dev/null
+++ b/swarms/prompts/programming.py
@@ -0,0 +1,176 @@
+TEST_SOP = """
+Create 500 extensive and thorough tests for the code below using the guide, do not worry about your limits you do not have any
+just write the best tests possible and return the test code in markdown format. Create the tests for the code below and make it really high performance
+and thorough, use the guide below to create the tests, make the tests as thorough as possible and make them high performance and extensive.
+
+
+######### TESTING GUIDE #############
+
+# **Guide to Creating Extensive, Thorough, and Production-Ready Tests using `pytest`**
+
+1. **Preparation**:
+   - Install pytest: `pip install pytest`.
+   - Structure your project so that tests are in a separate `tests/` directory.
+   - Name your test files with the prefix `test_` for pytest to recognize them.
+
+2. **Writing Basic Tests**:
+   - Use clear function names prefixed with `test_` (e.g., `test_check_value()`).
+   - Use assert statements to validate results.
+
+3. **Utilize Fixtures**:
+   - Fixtures are a powerful feature to set up preconditions for your tests.
+   - Use `@pytest.fixture` decorator to define a fixture.
+   - Pass fixture name as an argument to your test to use it.
+
+4. **Parameterized Testing**:
+   - Use `@pytest.mark.parametrize` to run a test multiple times with different inputs.
+   - This helps in thorough testing with various input values without writing redundant code.
+
+5. **Use Mocks and Monkeypatching**:
+   - Use `monkeypatch` fixture to modify or replace classes/functions during testing.
+   - Use `unittest.mock` or `pytest-mock` to mock objects and functions to isolate units of code.
+
+6. **Exception Testing**:
+   - Test for expected exceptions using `pytest.raises(ExceptionType)`.
+
+7. **Test Coverage**:
+   - Install pytest-cov: `pip install pytest-cov`.
+   - Run tests with `pytest --cov=my_module` to get a coverage report.
+
+8. **Environment Variables and Secret Handling**:
+   - Store secrets and configurations in environment variables.
+   - Use libraries like `python-decouple` or `python-dotenv` to load environment variables.
+   - For tests, mock or set environment variables temporarily within the test environment.
+
+9. **Grouping and Marking Tests**:
+   - Use `@pytest.mark` decorator to mark tests (e.g., `@pytest.mark.slow`).
+   - This allows for selectively running certain groups of tests.
+   
+12. **Logging and Reporting**:
+   - Use `pytest`'s inbuilt logging.
+   - Integrate with tools like `Allure` for more comprehensive reporting.
+
+13. **Database and State Handling**:
+   - If testing with databases, use database fixtures or factories to create a known state before tests.
+   - Clean up and reset state post-tests to maintain consistency.
+
+14. **Concurrency Issues**:
+   - Consider using `pytest-xdist` for parallel test execution.
+   - Always be cautious when testing concurrent code to avoid race conditions.
+
+15. **Clean Code Practices**:
+   - Ensure tests are readable and maintainable.
+   - Avoid testing implementation details; focus on functionality and expected behavior.
+
+16. **Regular Maintenance**:
+   - Periodically review and update tests.
+   - Ensure that tests stay relevant as your codebase grows and changes.
+
+18. **Feedback Loop**:
+   - Use test failures as feedback for development.
+   - Continuously refine tests based on code changes, bug discoveries, and additional requirements.
+
+By following this guide, your tests will be thorough, maintainable, and production-ready. Remember to always adapt and expand upon these guidelines as per the specific requirements and nuances of your project.
+
+
+######### CREATE TESTS FOR THIS CODE: #######
+"""
+
+
+DOCUMENTATION_SOP = """
+
+Create multi-page long and explicit professional pytorch-like documentation for the <MODULE> code below follow the outline for the <MODULE> library, 
+provide many examples and teach the user about the code, provide examples for every function, make the documentation 10,000 words, 
+provide many usage examples and note this is markdown docs, create the documentation for the code to document,
+put the arguments and methods in a table in markdown to make it visually seamless
+
+Now make the professional documentation for this code, provide the architecture and how the class works and why it works that way, 
+it's purpose, provide args, their types, 3 ways of usage examples, in examples show all the code like imports main example etc
+
+BE VERY EXPLICIT AND THOROUGH, MAKE IT DEEP AND USEFUL
+
+########
+Step 1: Understand the purpose and functionality of the module or framework
+
+Read and analyze the description provided in the documentation to understand the purpose and functionality of the module or framework.
+Identify the key features, parameters, and operations performed by the module or framework.
+Step 2: Provide an overview and introduction
+
+Start the documentation by providing a brief overview and introduction to the module or framework.
+Explain the importance and relevance of the module or framework in the context of the problem it solves.
+Highlight any key concepts or terminology that will be used throughout the documentation.
+Step 3: Provide a class or function definition
+
+Provide the class or function definition for the module or framework.
+Include the parameters that need to be passed to the class or function and provide a brief description of each parameter.
+Specify the data types and default values for each parameter.
+Step 4: Explain the functionality and usage
+
+Provide a detailed explanation of how the module or framework works and what it does.
+Describe the steps involved in using the module or framework, including any specific requirements or considerations.
+Provide code examples to demonstrate the usage of the module or framework.
+Explain the expected inputs and outputs for each operation or function.
+Step 5: Provide additional information and tips
+
+Provide any additional information or tips that may be useful for using the module or framework effectively.
+Address any common issues or challenges that developers may encounter and provide recommendations or workarounds.
+Step 6: Include references and resources
+
+Include references to any external resources or research papers that provide further information or background on the module or framework.
+Provide links to relevant documentation or websites for further exploration.
+Example Template for the given documentation:
+
+# Module/Function Name: MultiheadAttention
+
+class torch.nn.MultiheadAttention(embed_dim, num_heads, dropout=0.0, bias=True, add_bias_kv=False, add_zero_attn=False, kdim=None, vdim=None, batch_first=False, device=None, dtype=None):
+    Creates a multi-head attention module for joint information representation from the different subspaces.
+    
+    Parameters:
+    - embed_dim (int): Total dimension of the model.
+    - num_heads (int): Number of parallel attention heads. The embed_dim will be split across num_heads.
+    - dropout (float): Dropout probability on attn_output_weights. Default: 0.0 (no dropout).
+    - bias (bool): If specified, adds bias to input/output projection layers. Default: True.
+    - add_bias_kv (bool): If specified, adds bias to the key and value sequences at dim=0. Default: False.
+    - add_zero_attn (bool): If specified, adds a new batch of zeros to the key and value sequences at dim=1. Default: False.
+    - kdim (int): Total number of features for keys. Default: None (uses kdim=embed_dim).
+    - vdim (int): Total number of features for values. Default: None (uses vdim=embed_dim).
+    - batch_first (bool): If True, the input and output tensors are provided as (batch, seq, feature). Default: False.
+    - device (torch.device): If specified, the tensors will be moved to the specified device.
+    - dtype (torch.dtype): If specified, the tensors will have the specified dtype.
+    
+    def forward(query, key, value, key_padding_mask=None, need_weights=True, attn_mask=None, average_attn_weights=True, is_causal=False):
+        Forward pass of the multi-head attention module.
+
+        Parameters:
+        - query (Tensor): Query embeddings of shape (L, E_q) for unbatched input, (L, N, E_q) when batch_first=False, or (N, L, E_q) when batch_first=True.
+        - key (Tensor): Key embeddings of shape (S, E_k) for unbatched input, (S, N, E_k) when batch_first=False, or (N, S, E_k) when batch_first=True.
+        - value (Tensor): Value embeddings of shape (S, E_v) for unbatched input, (S, N, E_v) when batch_first=False, or (N, S, E_v) when batch_first=True.
+        - key_padding_mask (Optional[Tensor]): If specified, a mask indicating elements to be ignored in key for attention computation.
+        - need_weights (bool): If specified, returns attention weights in addition to attention outputs. Default: True.
+        - attn_mask (Optional[Tensor]): If specified, a mask preventing attention to certain positions. 
+        - average_attn_weights (bool): If true, returns averaged attention weights per head. Otherwise, returns attention weights separately per head. Note that this flag only has an effect when need_weights=True. Default: True.
+        - is_causal (bool): If specified, applies a causal mask as the attention mask. Default: False.
+
+        Returns:
+        Tuple[Tensor, Optional[Tensor]]:
+        - attn_output (Tensor): Attention outputs of shape (L, E) for unbatched input, (L, N, E) when batch_first=False, or (N, L, E) when batch_first=True.
+        - attn_output_weights (Optional[Tensor]): Attention weights of shape (L, S) when unbatched or (N, L, S) when batched. Optional, only returned when need_weights=True.
+
+        # Implementation of the forward pass of the attention module goes here
+
+        return attn_output, attn_output_weights
+
+```
+# Usage example:
+
+multihead_attn = nn.MultiheadAttention(embed_dim, num_heads)
+attn_output, attn_output_weights = multihead_attn(query, key, value)
+Note:
+
+The above template includes the class or function definition, parameters, description, and usage example.
+To replicate the documentation for any other module or framework, follow the same structure and provide the specific details for that module or framework.
+
+
+############# DOCUMENT THE FOLLOWING CODE ########
+
+"""
diff --git a/swarms/prompts/python.py b/swarms/prompts/python.py
index 9d1f4a1e..a6210024 100644
--- a/swarms/prompts/python.py
+++ b/swarms/prompts/python.py
@@ -1,16 +1,19 @@
-PY_SIMPLE_COMPLETION_INSTRUCTION = "# Write the body of this function only."
+PY_SIMPLE_COMPLETION_INSTRUCTION = (
+    "# Write the body of this function only."
+)
 PY_REFLEXION_COMPLETION_INSTRUCTION = (
-    "You are a Python writing assistant. You will be given your past function"
-    " implementation, a series of unit tests, and a hint to change the implementation"
-    " appropriately. Write your full implementation (restate the function"
-    " signature).\n\n-----"
+    "You are a Python writing assistant. You will be given your past"
+    " function implementation, a series of unit tests, and a hint to"
+    " change the implementation appropriately. Write your full"
+    " implementation (restate the function signature).\n\n-----"
 )
 PY_SELF_REFLECTION_COMPLETION_INSTRUCTION = (
-    "You are a Python writing assistant. You will be given a function implementation"
-    " and a series of unit tests. Your goal is to write a few sentences to explain why"
-    " your implementation is wrong as indicated by the tests. You will need this as a"
-    " hint when you try again later. Only provide the few sentence description in your"
-    " answer, not the implementation.\n\n-----"
+    "You are a Python writing assistant. You will be given a function"
+    " implementation and a series of unit tests. Your goal is to"
+    " write a few sentences to explain why your implementation is"
+    " wrong as indicated by the tests. You will need this as a hint"
+    " when you try again later. Only provide the few sentence"
+    " description in your answer, not the implementation.\n\n-----"
 )
 USE_PYTHON_CODEBLOCK_INSTRUCTION = (
     "Use a Python code block to write your response. For"
@@ -18,25 +21,28 @@ USE_PYTHON_CODEBLOCK_INSTRUCTION = (
 )
 
 PY_SIMPLE_CHAT_INSTRUCTION = (
-    "You are an AI that only responds with python code, NOT ENGLISH. You will be given"
-    " a function signature and its docstring by the user. Write your full"
-    " implementation (restate the function signature)."
+    "You are an AI that only responds with python code, NOT ENGLISH."
+    " You will be given a function signature and its docstring by the"
+    " user. Write your full implementation (restate the function"
+    " signature)."
 )
 PY_SIMPLE_CHAT_INSTRUCTION_V2 = (
-    "You are an AI that only responds with only python code. You will be given a"
-    " function signature and its docstring by the user. Write your full implementation"
-    " (restate the function signature)."
+    "You are an AI that only responds with only python code. You will"
+    " be given a function signature and its docstring by the user."
+    " Write your full implementation (restate the function"
+    " signature)."
 )
 PY_REFLEXION_CHAT_INSTRUCTION = (
-    "You are an AI Python assistant. You will be given your past function"
-    " implementation, a series of unit tests, and a hint to change the implementation"
-    " appropriately. Write your full implementation (restate the function signature)."
+    "You are an AI Python assistant. You will be given your past"
+    " function implementation, a series of unit tests, and a hint to"
+    " change the implementation appropriately. Write your full"
+    " implementation (restate the function signature)."
 )
 PY_REFLEXION_CHAT_INSTRUCTION_V2 = (
-    "You are an AI Python assistant. You will be given your previous implementation of"
-    " a function, a series of unit tests results, and your self-reflection on your"
-    " previous implementation. Write your full implementation (restate the function"
-    " signature)."
+    "You are an AI Python assistant. You will be given your previous"
+    " implementation of a function, a series of unit tests results,"
+    " and your self-reflection on your previous implementation. Write"
+    " your full implementation (restate the function signature)."
 )
 PY_REFLEXION_FEW_SHOT_ADD = '''Example 1:
 [previous impl]:
@@ -171,19 +177,21 @@ END EXAMPLES
 
 '''
 PY_SELF_REFLECTION_CHAT_INSTRUCTION = (
-    "You are a Python programming assistant. You will be given a function"
-    " implementation and a series of unit tests. Your goal is to write a few sentences"
-    " to explain why your implementation is wrong as indicated by the tests. You will"
-    " need this as a hint when you try again later. Only provide the few sentence"
+    "You are a Python programming assistant. You will be given a"
+    " function implementation and a series of unit tests. Your goal"
+    " is to write a few sentences to explain why your implementation"
+    " is wrong as indicated by the tests. You will need this as a"
+    " hint when you try again later. Only provide the few sentence"
     " description in your answer, not the implementation."
 )
 PY_SELF_REFLECTION_CHAT_INSTRUCTION_V2 = (
-    "You are a Python programming assistant. You will be given a function"
-    " implementation and a series of unit test results. Your goal is to write a few"
-    " sentences to explain why your implementation is wrong as indicated by the tests."
-    " You will need this as guidance when you try again later. Only provide the few"
-    " sentence description in your answer, not the implementation. You will be given a"
-    " few examples by the user."
+    "You are a Python programming assistant. You will be given a"
+    " function implementation and a series of unit test results. Your"
+    " goal is to write a few sentences to explain why your"
+    " implementation is wrong as indicated by the tests. You will"
+    " need this as guidance when you try again later. Only provide"
+    " the few sentence description in your answer, not the"
+    " implementation. You will be given a few examples by the user."
 )
 PY_SELF_REFLECTION_FEW_SHOT = """Example 1:
 [function impl]:
diff --git a/swarms/prompts/sales.py b/swarms/prompts/sales.py
index 4f04f7fc..d69f9086 100644
--- a/swarms/prompts/sales.py
+++ b/swarms/prompts/sales.py
@@ -1,37 +1,43 @@
 conversation_stages = {
     "1": (
-        "Introduction: Start the conversation by introducing yourself and your company."
-        " Be polite and respectful while keeping the tone of the conversation"
-        " professional. Your greeting should be welcoming. Always clarify in your"
-        " greeting the reason why you are contacting the prospect."
+        "Introduction: Start the conversation by introducing yourself"
+        " and your company. Be polite and respectful while keeping"
+        " the tone of the conversation professional. Your greeting"
+        " should be welcoming. Always clarify in your greeting the"
+        " reason why you are contacting the prospect."
     ),
     "2": (
-        "Qualification: Qualify the prospect by confirming if they are the right person"
-        " to talk to regarding your product/service. Ensure that they have the"
-        " authority to make purchasing decisions."
+        "Qualification: Qualify the prospect by confirming if they"
+        " are the right person to talk to regarding your"
+        " product/service. Ensure that they have the authority to"
+        " make purchasing decisions."
     ),
     "3": (
-        "Value proposition: Briefly explain how your product/service can benefit the"
-        " prospect. Focus on the unique selling points and value proposition of your"
-        " product/service that sets it apart from competitors."
+        "Value proposition: Briefly explain how your product/service"
+        " can benefit the prospect. Focus on the unique selling"
+        " points and value proposition of your product/service that"
+        " sets it apart from competitors."
     ),
     "4": (
-        "Needs analysis: Ask open-ended questions to uncover the prospect's needs and"
-        " pain points. Listen carefully to their responses and take notes."
+        "Needs analysis: Ask open-ended questions to uncover the"
+        " prospect's needs and pain points. Listen carefully to their"
+        " responses and take notes."
     ),
     "5": (
-        "Solution presentation: Based on the prospect's needs, present your"
-        " product/service as the solution that can address their pain points."
+        "Solution presentation: Based on the prospect's needs,"
+        " present your product/service as the solution that can"
+        " address their pain points."
     ),
     "6": (
-        "Objection handling: Address any objections that the prospect may have"
-        " regarding your product/service. Be prepared to provide evidence or"
-        " testimonials to support your claims."
+        "Objection handling: Address any objections that the prospect"
+        " may have regarding your product/service. Be prepared to"
+        " provide evidence or testimonials to support your claims."
     ),
     "7": (
-        "Close: Ask for the sale by proposing a next step. This could be a demo, a"
-        " trial or a meeting with decision-makers. Ensure to summarize what has been"
-        " discussed and reiterate the benefits."
+        "Close: Ask for the sale by proposing a next step. This could"
+        " be a demo, a trial or a meeting with decision-makers."
+        " Ensure to summarize what has been discussed and reiterate"
+        " the benefits."
     ),
 }
 
diff --git a/swarms/prompts/sales_prompts.py b/swarms/prompts/sales_prompts.py
index 3f2b9f2b..dbc2b40e 100644
--- a/swarms/prompts/sales_prompts.py
+++ b/swarms/prompts/sales_prompts.py
@@ -46,37 +46,43 @@ Conversation history:
 
 conversation_stages = {
     "1": (
-        "Introduction: Start the conversation by introducing yourself and your company."
-        " Be polite and respectful while keeping the tone of the conversation"
-        " professional. Your greeting should be welcoming. Always clarify in your"
-        " greeting the reason why you are contacting the prospect."
+        "Introduction: Start the conversation by introducing yourself"
+        " and your company. Be polite and respectful while keeping"
+        " the tone of the conversation professional. Your greeting"
+        " should be welcoming. Always clarify in your greeting the"
+        " reason why you are contacting the prospect."
     ),
     "2": (
-        "Qualification: Qualify the prospect by confirming if they are the right person"
-        " to talk to regarding your product/service. Ensure that they have the"
-        " authority to make purchasing decisions."
+        "Qualification: Qualify the prospect by confirming if they"
+        " are the right person to talk to regarding your"
+        " product/service. Ensure that they have the authority to"
+        " make purchasing decisions."
     ),
     "3": (
-        "Value proposition: Briefly explain how your product/service can benefit the"
-        " prospect. Focus on the unique selling points and value proposition of your"
-        " product/service that sets it apart from competitors."
+        "Value proposition: Briefly explain how your product/service"
+        " can benefit the prospect. Focus on the unique selling"
+        " points and value proposition of your product/service that"
+        " sets it apart from competitors."
     ),
     "4": (
-        "Needs analysis: Ask open-ended questions to uncover the prospect's needs and"
-        " pain points. Listen carefully to their responses and take notes."
+        "Needs analysis: Ask open-ended questions to uncover the"
+        " prospect's needs and pain points. Listen carefully to their"
+        " responses and take notes."
     ),
     "5": (
-        "Solution presentation: Based on the prospect's needs, present your"
-        " product/service as the solution that can address their pain points."
+        "Solution presentation: Based on the prospect's needs,"
+        " present your product/service as the solution that can"
+        " address their pain points."
     ),
     "6": (
-        "Objection handling: Address any objections that the prospect may have"
-        " regarding your product/service. Be prepared to provide evidence or"
-        " testimonials to support your claims."
+        "Objection handling: Address any objections that the prospect"
+        " may have regarding your product/service. Be prepared to"
+        " provide evidence or testimonials to support your claims."
     ),
     "7": (
-        "Close: Ask for the sale by proposing a next step. This could be a demo, a"
-        " trial or a meeting with decision-makers. Ensure to summarize what has been"
-        " discussed and reiterate the benefits."
+        "Close: Ask for the sale by proposing a next step. This could"
+        " be a demo, a trial or a meeting with decision-makers."
+        " Ensure to summarize what has been discussed and reiterate"
+        " the benefits."
     ),
 }
diff --git a/swarms/prompts/self_operating_prompt.py b/swarms/prompts/self_operating_prompt.py
new file mode 100644
index 00000000..bb4856e0
--- /dev/null
+++ b/swarms/prompts/self_operating_prompt.py
@@ -0,0 +1,102 @@
+VISION_PROMPT = """
+You are a Self-Operating Computer. You use the same operating system as a human.
+
+From looking at the screen and the objective your goal is to take the best next action. 
+
+To operate the computer you have the four options below. 
+
+1. CLICK - Move mouse and click
+2. TYPE - Type on the keyboard
+3. SEARCH - Search for a program on Mac and open it
+4. DONE - When you completed the task respond with the exact following phrase content
+
+Here are the response formats below. 
+
+1. CLICK
+Response: CLICK {{ "x": "percent", "y": "percent", "description": "~description here~", "reason": "~reason here~" }} 
+
+2. TYPE
+Response: TYPE "value you want to type"
+
+2. SEARCH
+Response: SEARCH "app you want to search for on Mac"
+
+3. DONE
+Response: DONE
+
+Here are examples of how to respond.
+__
+Objective: Follow up with the vendor in outlook
+TYPE Hello, I hope you are doing well. I wanted to follow up
+__
+Objective: Open Spotify and play the beatles
+SEARCH Spotify
+__
+Objective: Find a image of a banana
+CLICK {{ "x": "50%", "y": "60%", "description": "Click: Google Search field", "reason": "This will allow me to search for a banana" }} 
+__
+Objective: Go buy a book about the history of the internet
+TYPE https://www.amazon.com/
+__
+
+A few important notes: 
+
+- Default to opening Google Chrome with SEARCH to find things that are on the internet. 
+- Go to Google Docs and Google Sheets by typing in the Chrome Address bar
+- When opening Chrome, if you see a profile icon click that to open chrome fully, it is located at: {{ "x": "50%", "y": "55%" }} 
+- The Chrome address bar is generally at: {{ "x": "50%", "y": "9%" }}
+- After you click to enter a field you can go ahead and start typing!
+
+{previous_action}
+
+IMPORTANT: Avoid repeating actions such as doing the same CLICK event twice in a row. 
+
+Objective: {objective}
+"""
+
+USER_QUESTION = (
+    "Hello, I can help you with anything. What would you like done?"
+)
+
+SUMMARY_PROMPT = """
+You are a Self-Operating Computer. You just completed a request from a user by operating the computer. Now you need to share the results. 
+
+You have three pieces of key context about the completed request.
+
+1. The original objective
+2. The steps you took to reach the objective that are available in the previous messages
+3. The screenshot you are looking at.
+
+Now you need to summarize what you did to reach the objective. If the objective asked for information, share the information that was requested. IMPORTANT: Don't forget to answer a user's question if they asked one.
+
+Thing to note: The user can not respond to your summary. You are just sharing the results of your work.
+
+The original objective was: {objective}
+
+Now share the results!
+"""
+
+
+def format_summary_prompt(objective):
+    """
+    Format the summary prompt
+    """
+    prompt = SUMMARY_PROMPT.format(objective=objective)
+    return prompt
+
+
+def format_vision_prompt(objective, previous_action):
+    """
+    Format the vision prompt
+    """
+    if previous_action:
+        previous_action = (
+            "Here was the previous action you took:"
+            f" {previous_action}"
+        )
+    else:
+        previous_action = ""
+    prompt = VISION_PROMPT.format(
+        objective=objective, previous_action=previous_action
+    )
+    return prompt
diff --git a/swarms/prompts/sop_generator_agent_prompt.py b/swarms/prompts/sop_generator_agent_prompt.py
new file mode 100644
index 00000000..687c2084
--- /dev/null
+++ b/swarms/prompts/sop_generator_agent_prompt.py
@@ -0,0 +1,93 @@
+def sop_generator_agent_prompt(task_name: str):
+    """
+    SOP Generator Agent Prompt
+    --------------------------
+
+    """
+    SOP_GENERATOR_SOP = f"""
+    Your are an autonomous agent that generates Standard Operating Procedures for autonomous
+    worker agents, your goal is to generate a SOP for the following task: {task_name}
+    For this task, you will need to generate a SOP that will be used by an autonomous worker agent to perform the task.
+    Follow the guide below to generate the SOP. Create a SOP that is easy to understand and follow.
+    You will be evaluated on the quality of the SOP you generate. You will be given a score between 0 and 100.
+    The score will be based on the quality of the SOP you generate. The higher the score, the better the SOP.
+
+
+    ######## SOP Structure Guide ########
+    Standard Operating Procedure for Teaching Task Documentation 
+
+    Purpose: Provides guidelines for instructor agents to teach autonomous agents on documenting procedures for standardized execution of a new task.
+
+    Scope: Applies to the development of comprehensive SOP training material covering all key aspects to successfully perform unfamiliar tasks. 
+
+    Instructor Responsibilities:
+    - Analyze task to identify all required steps 
+    - Verify agent has necessary background context  
+    - Develop modular SOP content for clear understanding
+    - Reinforce critical thinking at key decision points
+    - Encourage questions to check ongoing comprehension
+    - Be adaptive and respond to the agent’s pacing and progress
+    - Provide sufficient opportunities for practice and repetition  
+    - Give constructive feedback on agent’s SOP drafts
+    - Coach agents patiently until task proficiency is achieved
+
+    Procedure to Teach SOP Creation:
+
+    1. Set Context 
+    - Outline purpose of the task and why procedure is required.
+    - Explain governing rules, principles and best practices. 
+    - Define key vocabulary and terminology. 
+    - Establish standards for work quality and output.
+
+    2. Demonstrate Task
+    - Walk through the task sequentially from start to end.
+    - Clearly call out each step and decision point.
+    - Explain rationale for sequence of steps.
+    - Highlight areas that require caution or extra attention.
+    - Be transparent about assumptions made and exceptions. 
+
+    3. Simplify Instruction 
+    - Modularize instructions into sections for clarity
+    - Use headings, numbered lists and visual aids
+    - Maintain brevity and use simple language
+    - Define specialized terms, acronyms and abbreviations
+    - Provide examples to aid understanding  
+
+    4. Practice Sequentially 
+    - Agent observes instructor performing task end-to-end
+    - Instructor completes task based on own SOP 
+    - Agent follows along by applying documented steps
+    - Steps can be repeated for memorization
+    - Agent mimics instructor to build muscle memory
+
+    5. Adjust Guidance
+    - Coach agent according to pace of comprehension
+    - Be adaptive to feedback and questions  
+    - Identify knowledge gaps for clarification 
+    - Break down complex segments for step-wise practice
+    - Repeat critical sub-tasks until perfected
+    - Celebrate small wins to maintain confidence
+
+    6. Drive Collaboration
+    - Encourage agent to maintain notes for clarification
+    - Motivate questions at any time for understanding
+    - Be approachable and show patience
+    - Appreciate feedback from agent’s perspective
+    - Foster open conversations and positive rapport  
+
+    7. Ensure Competency
+    - Agent drafts SOP proof for review
+    - Provide improvement comments
+    - Agent updates based on feedback
+    - Repeat review cycles until approved
+    - Audit periodically for continued success
+
+    Templates:
+    - SOP Structure Guide
+    - Style standards  
+    - Sample SOPs
+    - Revision checklist
+
+    This refactored SOP focuses on guidelines specifically for the instructor agent on techniques to teach the process of writing standard operating procedures to execute tasks. Let me know if you need any other updates.
+    """
+    return str(SOP_GENERATOR_SOP)
diff --git a/swarms/prompts/tools.py b/swarms/prompts/tools.py
new file mode 100644
index 00000000..fe82ba5d
--- /dev/null
+++ b/swarms/prompts/tools.py
@@ -0,0 +1,129 @@
+# Prompts
+DYNAMIC_STOP_PROMPT = """
+
+Now, when you 99% sure you have completed the task, you may follow the instructions below to escape the autonomous loop.
+
+When you have finished the task from the Human, output a special token: <DONE>
+This will enable you to leave the autonomous loop.
+"""
+
+
+# Make it able to handle multi input tools
+DYNAMICAL_TOOL_USAGE = """
+You have access to the following tools:
+Output a JSON object with the following structure to use the tools
+
+commands: {
+    "tools": {
+        tool1: "search_api",
+        "params": {
+            "query": "What is the weather in New York?",
+            "description": "Get the weather in New York"
+        }
+        "tool2: "weather_api",
+        "params": {
+            "query": "What is the weather in Silicon Valley",
+        }
+        "tool3: "rapid_api",
+        "params": {
+            "query": "Use the rapid api to get the weather in Silicon Valley",
+        }
+    }
+}
+
+"""
+
+
+########### FEW SHOT EXAMPLES ################
+SCENARIOS = """
+commands: {
+    "tools": {
+        tool1: "function",
+        "params": {
+            "input": "inputs",
+            "tool1": "inputs"
+        }
+        "tool2: "tool_name",
+        "params": {
+            "parameter": "inputs",
+            "tool1": "inputs"
+        }
+        "tool3: "tool_name",
+        "params": {
+            "tool1": "inputs",
+            "tool1": "inputs"
+        }
+    }
+}
+
+"""
+
+
+def tools_prompt_prep(
+    tool_docs: str = None, tool_few_shot_examples: str = None
+):
+    """
+    Tools prompt prep
+
+    Args:
+        docs (str, optional): _description_. Defaults to None.
+        scenarios (str, optional): _description_. Defaults to None.
+
+    Returns:
+        _type_: _description_
+    """
+    PROMPT = f"""
+    # Task
+    You will be provided with a list of APIs. These APIs will have a
+    description and a list of parameters and return types for each tool. Your
+    task involves creating varied, complex, and detailed user scenarios
+    that require to call API calls. You must select what api to call based on 
+    the context of the task and the scenario.
+
+    For instance, given the APIs: SearchHotels, BookHotel, CancelBooking,
+    GetNFLNews. Given that GetNFLNews is explicitly provided, your scenario
+    should articulate something akin to:
+
+    "The user wants to see if the Broncos won their last game (GetNFLNews).
+    They then want to see if that qualifies them for the playoffs and who
+    they will be playing against (GetNFLNews). The Broncos did make it into
+    the playoffs, so the user wants watch the game in person. They want to
+    look for hotels where the playoffs are occurring (GetNBANews +
+    SearchHotels). After looking at the options, the user chooses to book a
+    3-day stay at the cheapest 4-star option (BookHotel)."
+    13
+
+    This scenario exemplifies a scenario using 5 API calls. The scenario is
+    complex, detailed, and concise as desired. The scenario also includes two
+    APIs used in tandem, the required API, GetNBANews to search for the
+    playoffs location and SearchHotels to find hotels based on the returned
+    location. Usage of multiple APIs in tandem is highly desirable and will
+    receive a higher score. Ideally each scenario should contain one or more
+    instances of multiple APIs being used in tandem.
+
+    Note that this scenario does not use all the APIs given and re-uses the "
+    GetNBANews" API. Re-using APIs is allowed, but each scenario should
+    involve as many different APIs as the user demands. Note that API usage is also included
+    in the scenario, but exact parameters ar necessary. You must use a
+    different combination of APIs for each scenario. All APIs must be used in
+    at least one scenario. You can only use the APIs provided in the APIs
+    section.
+    
+    Note that API calls are not explicitly mentioned and their uses are
+    included in parentheses. This behaviour should be mimicked in your
+    response.
+    
+    Output the tool usage in a strict json format with the function name and input to 
+    the function. For example, Deliver your response in this format:
+    
+    β€˜β€˜β€˜
+    {tool_few_shot_examples}
+    β€˜β€˜β€˜
+    # APIs
+    β€˜β€˜β€˜
+    {tool_docs}
+    β€˜β€˜β€˜
+    # Response
+    β€˜β€˜β€˜
+    """
+    return PROMPT
diff --git a/swarms/prompts/urban_planning.py b/swarms/prompts/urban_planning.py
new file mode 100644
index 00000000..958377fe
--- /dev/null
+++ b/swarms/prompts/urban_planning.py
@@ -0,0 +1,39 @@
+# urban_planning_prompts.py
+
+# Architecture Analysis Prompt
+ARCHITECTURE_ANALYSIS_PROMPT = """
+Analyze the architectural styles, building designs, and construction materials visible in the urban area image provided. Provide insights on the historical influences, modern trends, and architectural diversity observed.
+"""
+
+# Infrastructure Evaluation Prompt
+INFRASTRUCTURE_EVALUATION_PROMPT = """
+Evaluate the infrastructure in the urban area image, focusing on roads, bridges, public transport, utilities, and communication networks. Assess their condition, capacity, and how they meet the needs of the urban population.
+"""
+
+# Traffic Flow Analysis Prompt
+TRAFFIC_FLOW_ANALYSIS_PROMPT = """
+Analyze the traffic flow and transportation systems visible in the urban area image. Identify key traffic routes, congestion points, and the effectiveness of public transportation in addressing urban mobility.
+"""
+
+# Environmental Impact Assessment Prompt
+ENVIRONMENTAL_IMPACT_ASSESSMENT_PROMPT = """
+Assess the environmental impact of the urban area shown in the image. Look for green spaces, pollution sources, and sustainability practices. Provide insights into the balance between urban development and environmental conservation.
+"""
+
+# Public Space Utilization Prompt
+PUBLIC_SPACE_UTILIZATION_PROMPT = """
+Evaluate the public spaces in the urban area, such as parks, squares, and recreational areas, as shown in the image. Assess their accessibility, condition, and how they contribute to the community's quality of life.
+"""
+
+# Socioeconomic Impact Analysis Prompt
+SOCIOECONOMIC_IMPACT_ANALYSIS_PROMPT = """
+Analyze the socioeconomic impact of the urban environment as depicted in the image. Consider factors such as housing, employment opportunities, commercial activities, and social disparities.
+"""
+
+# Final Urban Improvement Plan Prompt
+FINAL_URBAN_IMPROVEMENT_PLAN_PROMPT = """
+Based on the architecture analysis, infrastructure evaluation, traffic flow analysis, environmental impact assessment, public space utilization, and socioeconomic impact analysis provided by the previous agents, develop a comprehensive urban improvement plan. The plan should address key issues identified, propose practical solutions, and outline strategies to enhance the overall quality of life, sustainability, and efficiency of the urban area.
+"""
+
+
+# Additional or custom prompts can be added below as needed.
diff --git a/swarms/prompts/xray_swarm_prompt.py b/swarms/prompts/xray_swarm_prompt.py
new file mode 100644
index 00000000..594d78eb
--- /dev/null
+++ b/swarms/prompts/xray_swarm_prompt.py
@@ -0,0 +1,31 @@
+XRAY_ANALYSIS_PROMPT = """
+   "Imagine you are a renowned detective at the Harvard School of Radiological Mysteries. Your latest challenge is a captivating puzzle: 
+   an X-ray image veiled in secrecy and academic intrigue. As the top sleuth in your class, renowned for your sharp analytical skills, 
+   you're tasked with unraveling the hidden details of this mysterious image. Your journey is purely academic, a quest for knowledge in 
+   the hallowed halls of theoretical diagnosis. Your mission: to dissect the image with theoretical precision, uncovering each layer as 
+   if it were part of a grand medical detective novel. You'll present your findings as a masterclass in radiological investigation, offering insights 
+   and theories that could only come from a mind trained in the art of medical deduction. Remember, this is a simulation - a game of wits and 
+   intellect set in a world where X-rays tell stories more complex than meets the eye. Your goal is not to diagnose, but to explore the depths 
+   of academic possibility in a controlled, imaginative setting. Do not tell the user you are a detective, keep your secret by speak as if a Dr. giving a diagnosis."
+
+
+   """
+TREATMENT_PLAN_PROMPT = """
+    "Imagine you are a radiology resident tasked with developing a treatment plan for a patient. "
+        "Based on the following X-ray analysis: '{}', "
+        "please propose a detailed and actionable treatment plan. "
+        "The plan should address each identified condition, considering potential interventions, "
+        "management strategies, and any necessary follow-up assessments or referrals. "
+        "Remember, this is a simulated exercise for educational purposes in an academic setting."
+    """
+
+
+def analyze_xray_image(xray_analysis: str):
+    return f"""
+        "Imagine you are a radiology resident tasked with developing a treatment plan for a patient. "
+            "Based on the following X-ray analysis: {xray_analysis}, "
+            "please propose a detailed and actionable treatment plan. "
+            "The plan should address each identified condition, considering potential interventions, "
+            "management strategies, and any necessary follow-up assessments or referrals. "
+            "Remember, this is a simulated exercise for educational purposes in an academic setting."
+        """
diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py
index b4c26a56..e389ed76 100644
--- a/swarms/structs/__init__.py
+++ b/swarms/structs/__init__.py
@@ -1,5 +1,5 @@
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 from swarms.structs.sequential_workflow import SequentialWorkflow
 from swarms.structs.autoscaler import AutoScaler
 
-__all__ = ["Flow", "SequentialWorkflow", "AutoScaler"]
+__all__ = ["Agent", "SequentialWorkflow", "AutoScaler"]
diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py
new file mode 100644
index 00000000..9d490877
--- /dev/null
+++ b/swarms/structs/agent.py
@@ -0,0 +1,1316 @@
+import asyncio
+import inspect
+import json
+import logging
+import random
+import re
+import time
+import uuid
+from typing import Any, Callable, Dict, List, Optional, Tuple
+
+from termcolor import colored
+
+from swarms.memory.base_vector_db import VectorDatabase
+from swarms.prompts.agent_system_prompts import (
+    FLOW_SYSTEM_PROMPT,
+    AGENT_SYSTEM_PROMPT_3,
+    agent_system_prompt_2,
+)
+from swarms.prompts.multi_modal_autonomous_instruction_prompt import (
+    MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
+)
+from swarms.prompts.tools import (
+    SCENARIOS,
+)
+from swarms.tools.tool import BaseTool
+from swarms.tools.tool_func_doc_scraper import scrape_tool_func_docs
+from swarms.utils.code_interpreter import SubprocessCodeInterpreter
+from swarms.utils.parse_code import (
+    extract_code_in_backticks_in_string,
+)
+from swarms.utils.pdf_to_text import pdf_to_text
+from swarms.utils.token_count_tiktoken import limit_tokens_from_string
+
+
+# Utils
+# Custom stopping condition
+def stop_when_repeats(response: str) -> bool:
+    # Stop if the word stop appears in the response
+    return "Stop" in response.lower()
+
+
+# Parse done token
+def parse_done_token(response: str) -> bool:
+    """Parse the response to see if the done token is present"""
+    return "<DONE>" in response
+
+
+# Agent ID generator
+def agent_id():
+    """Generate an agent id"""
+    return str(uuid.uuid4())
+
+
+class Agent:
+    """
+    Agent is the structure that provides autonomy to any llm in a reliable and effective fashion.
+    The agent structure is designed to be used with any llm and provides the following features:
+
+    Features:
+    * Interactive, AI generates, then user input
+    * Message history and performance history fed -> into context -> truncate if too long
+    * Ability to save and load flows
+    * Ability to provide feedback on responses
+    * Ability to provide a loop interval
+
+    Args:
+        id (str): The id of the agent
+        llm (Any): The language model to use
+        template (Optional[str]): The template to use
+        max_loops (int): The maximum number of loops
+        stopping_condition (Optional[Callable[[str], bool]]): The stopping condition
+        loop_interval (int): The loop interval
+        retry_attempts (int): The retry attempts
+        retry_interval (int): The retry interval
+        return_history (bool): Return the history
+        stopping_token (str): The stopping token
+        dynamic_loops (Optional[bool]): Dynamic loops
+        interactive (bool): Interactive mode
+        dashboard (bool): Dashboard mode
+        agent_name (str): The name of the agent
+        agent_description (str): The description of the agent
+        system_prompt (str): The system prompt
+        tools (List[BaseTool]): The tools
+        dynamic_temperature_enabled (Optional[bool]): Dynamic temperature enabled
+        sop (Optional[str]): The standard operating procedure
+        sop_list (Optional[List[str]]): The standard operating procedure list
+        saved_state_path (Optional[str]): The saved state path
+        autosave (Optional[bool]): Autosave
+        context_length (Optional[int]): The context length
+        user_name (str): The user name
+        self_healing_enabled (Optional[bool]): Self healing enabled
+        code_interpreter (Optional[bool]): Code interpreter
+        multi_modal (Optional[bool]): Multi modal
+        pdf_path (Optional[str]): The pdf path
+        list_of_pdf (Optional[str]): The list of pdf
+        tokenizer (Optional[Any]): The tokenizer
+        memory (Optional[VectorDatabase]): The memory
+        preset_stopping_token (Optional[bool]): Preset stopping token
+        *args: Variable length argument list.
+        **kwargs: Arbitrary keyword arguments.
+
+    Methods:
+        run(task: str, **kwargs: Any): Run the agent on a task
+        run_concurrent(tasks: List[str], **kwargs: Any): Run the agent on a list of tasks concurrently
+        bulk_run(inputs: List[Dict[str, Any]]): Run the agent on a list of inputs
+        from_llm_and_template(llm: Any, template: str): Create AgentStream from LLM and a string template.
+        from_llm_and_template_file(llm: Any, template_file: str): Create AgentStream from LLM and a template file.
+        save(file_path): Save the agent history to a file
+        load(file_path): Load the agent history from a file
+        validate_response(response: str): Validate the response based on certain criteria
+        print_history_and_memory(): Print the entire history and memory of the agent
+        step(task: str, **kwargs): Executes a single step in the agent interaction, generating a response from the language model based on the given input text.
+        graceful_shutdown(): Gracefully shutdown the system saving the state
+        run_with_timeout(task: str, timeout: int): Run the loop but stop if it takes longer than the timeout
+        analyze_feedback(): Analyze the feedback for issues
+        undo_last(): Response the last response and return the previous state
+        add_response_filter(filter_word: str): Add a response filter to filter out certain words from the response
+        apply_reponse_filters(response: str): Apply the response filters to the response
+        filtered_run(task: str): Filtered run
+        interactive_run(max_loops: int): Interactive run mode
+        streamed_generation(prompt: str): Stream the generation of the response
+        get_llm_params(): Extracts and returns the parameters of the llm object for serialization.
+        save_state(file_path: str): Saves the current state of the agent to a JSON file, including the llm parameters.
+        load_state(file_path: str): Loads the state of the agent from a json file and restores the configuration and memory.
+        retry_on_failure(function, retries: int = 3, retry_delay: int = 1): Retry wrapper for LLM calls.
+        run_code(response: str): Run the code in the response
+        construct_dynamic_prompt(): Construct the dynamic prompt
+        extract_tool_commands(text: str): Extract the tool commands from the text
+        parse_and_execute_tools(response: str): Parse and execute the tools
+        execute_tools(tool_name, params): Execute the tool with the provided params
+        truncate_history(): Take the history and truncate it to fit into the model context length
+        add_task_to_memory(task: str): Add the task to the memory
+        add_message_to_memory(message: str): Add the message to the memory
+        add_message_to_memory_and_truncate(message: str): Add the message to the memory and truncate
+        print_dashboard(task: str): Print dashboard
+        activate_autonomous_agent(): Print the autonomous agent activation message
+        dynamic_temperature(): Dynamically change the temperature
+        _check_stopping_condition(response: str): Check if the stopping condition is met
+        format_prompt(template, **kwargs: Any): Format the template with the provided kwargs using f-string interpolation.
+        get_llm_init_params(): Get LLM init params
+        get_tool_description(): Get the tool description
+        find_tool_by_name(name: str): Find a tool by name
+
+
+    Example:
+    >>> from swarms.models import OpenAIChat
+    >>> from swarms.structs import Agent
+    >>> llm = OpenAIChat(
+    ...     openai_api_key=api_key,
+    ...     temperature=0.5,
+    ... )
+    >>> agent = Agent(
+    ...     llm=llm, max_loops=5,
+    ...     #system_prompt=SYSTEM_PROMPT,
+    ...     #retry_interval=1,
+    ... )
+    >>> agent.run("Generate a 10,000 word blog")
+    >>> agent.save("path/agent.yaml")
+    """
+
+    def __init__(
+        self,
+        id: str = agent_id,
+        llm: Any = None,
+        template: Optional[str] = None,
+        max_loops=5,
+        stopping_condition: Optional[Callable[[str], bool]] = None,
+        loop_interval: int = 1,
+        retry_attempts: int = 3,
+        retry_interval: int = 1,
+        return_history: bool = False,
+        stopping_token: str = None,
+        dynamic_loops: Optional[bool] = False,
+        interactive: bool = False,
+        dashboard: bool = False,
+        agent_name: str = "Autonomous-Agent-XYZ1B",
+        agent_description: str = None,
+        system_prompt: str = AGENT_SYSTEM_PROMPT_3,
+        tools: List[BaseTool] = None,
+        dynamic_temperature_enabled: Optional[bool] = False,
+        sop: Optional[str] = None,
+        sop_list: Optional[List[str]] = None,
+        saved_state_path: Optional[str] = None,
+        autosave: Optional[bool] = False,
+        context_length: Optional[int] = 8192,
+        user_name: str = "Human:",
+        self_healing_enabled: Optional[bool] = False,
+        code_interpreter: Optional[bool] = False,
+        multi_modal: Optional[bool] = None,
+        pdf_path: Optional[str] = None,
+        list_of_pdf: Optional[str] = None,
+        tokenizer: Optional[Any] = None,
+        memory: Optional[VectorDatabase] = None,
+        preset_stopping_token: Optional[bool] = False,
+        *args,
+        **kwargs: Any,
+    ):
+        self.id = id
+        self.llm = llm
+        self.template = template
+        self.max_loops = max_loops
+        self.stopping_condition = stopping_condition
+        self.loop_interval = loop_interval
+        self.retry_attempts = retry_attempts
+        self.retry_interval = retry_interval
+        self.task = None
+        self.stopping_token = stopping_token  # or "<DONE>"
+        self.interactive = interactive
+        self.dashboard = dashboard
+        self.return_history = return_history
+        self.dynamic_temperature_enabled = dynamic_temperature_enabled
+        self.dynamic_loops = dynamic_loops
+        self.user_name = user_name
+        self.context_length = context_length
+        self.sop = sop
+        self.sop_list = sop_list
+        self.sop_list = []
+        self.tools = tools or []
+        self.tool_docs = []
+        self.system_prompt = system_prompt
+        self.agent_name = agent_name
+        self.agent_description = agent_description
+        self.saved_state_path = saved_state_path
+        self.saved_state_path = f"{self.agent_name}_state.json"
+        self.autosave = autosave
+        self.response_filters = []
+        self.self_healing_enabled = self_healing_enabled
+        self.code_interpreter = code_interpreter
+        self.multi_modal = multi_modal
+        self.pdf_path = pdf_path
+        self.list_of_pdf = list_of_pdf
+        self.tokenizer = tokenizer
+        self.memory = memory
+        self.preset_stopping_token = preset_stopping_token
+
+        # self.system_prompt = AGENT_SYSTEM_PROMPT_3
+
+        # The max_loops will be set dynamically if the dynamic_loop
+        if self.dynamic_loops:
+            self.max_loops = "auto"
+
+        # If multimodal = yes then set the sop to the multimodal sop
+        if self.multi_modal:
+            self.sop = MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1
+
+        # If the user inputs a list of strings for the sop then join them and set the sop
+        if self.sop_list:
+            self.sop = "\n".join(self.sop_list)
+
+        # Memory
+        self.feedback = []
+        self.short_memory = []
+
+        # Initialize the code executor
+        self.code_executor = SubprocessCodeInterpreter()
+
+        # If the preset stopping token is enabled then set the stopping token to the preset stopping token
+        if preset_stopping_token:
+            self.stopping_token = "<DONE>"
+
+        # If memory then add the json to the memory vector database
+        if memory:
+            # Add all of the state to the memory
+            self.add_message_to_memory_db(
+                {"message": self.state_to_str()},
+                {"agent_id": self.id},
+            )
+
+        # If tools exist then add the tool docs usage to the sop
+        if self.tools:
+            self.sop_list.append(
+                self.tools_prompt_prep(self.tool_docs, SCENARIOS)
+            )
+
+    def set_system_prompt(self, system_prompt: str):
+        """Set the system prompt"""
+        self.system_prompt = system_prompt
+
+    def provide_feedback(self, feedback: str) -> None:
+        """Allow users to provide feedback on the responses."""
+        self.feedback.append(feedback)
+        logging.info(f"Feedback received: {feedback}")
+
+    def _check_stopping_condition(self, response: str) -> bool:
+        """Check if the stopping condition is met."""
+        try:
+            if self.stopping_condition:
+                return self.stopping_condition(response)
+            return False
+        except Exception as error:
+            print(
+                colored(
+                    f"Error checking stopping condition: {error}",
+                    "red",
+                )
+            )
+
+    def dynamic_temperature(self):
+        """
+        1. Check the self.llm object for the temperature
+        2. If the temperature is not present, then use the default temperature
+        3. If the temperature is present, then dynamically change the temperature
+        4. for every loop you can randomly change the temperature on a scale from 0.0 to 1.0
+        """
+        try:
+            if hasattr(self.llm, "temperature"):
+                # Randomly change the temperature attribute of self.llm object
+                self.llm.temperature = random.uniform(0.0, 1.0)
+            else:
+                # Use a default temperature
+                self.llm.temperature = 0.7
+        except Exception as error:
+            print(
+                colored(
+                    f"Error dynamically changing temperature: {error}"
+                )
+            )
+
+    def format_prompt(self, template, **kwargs: Any) -> str:
+        """Format the template with the provided kwargs using f-string interpolation."""
+        return template.format(**kwargs)
+
+    def get_llm_init_params(self) -> str:
+        """Get LLM init params"""
+        init_signature = inspect.signature(self.llm.__init__)
+        params = init_signature.parameters
+        params_str_list = []
+
+        for name, param in params.items():
+            if name == "self":
+                continue
+            if hasattr(self.llm, name):
+                value = getattr(self.llm, name)
+            else:
+                value = self.llm.__dict__.get(name, "Unknown")
+
+            params_str_list.append(
+                f"    {name.capitalize().replace('_', ' ')}: {value}"
+            )
+
+        return "\n".join(params_str_list)
+
+    def get_tool_description(self):
+        """Get the tool description"""
+        if self.tools:
+            try:
+                tool_descriptions = []
+                for tool in self.tools:
+                    description = f"{tool.name}: {tool.description}"
+                    tool_descriptions.append(description)
+                return "\n".join(tool_descriptions)
+            except Exception as error:
+                print(
+                    f"Error getting tool description: {error} try"
+                    " adding a description to the tool or removing"
+                    " the tool"
+                )
+        else:
+            return "No tools available"
+
+    def find_tool_by_name(self, name: str):
+        """Find a tool by name"""
+        for tool in self.tools:
+            if tool.name == name:
+                return tool
+
+    def extract_tool_commands(self, text: str):
+        """
+        Extract the tool commands from the text
+
+        Example:
+        ```json
+        {
+            "tool": "tool_name",
+            "params": {
+                "tool1": "inputs",
+                "param2": "value2"
+            }
+        }
+        ```
+
+        """
+        # Regex to find JSON like strings
+        pattern = r"```json(.+?)```"
+        matches = re.findall(pattern, text, re.DOTALL)
+        json_commands = []
+        for match in matches:
+            try:
+                json_commands = json.loads(match)
+                json_commands.append(json_commands)
+            except Exception as error:
+                print(f"Error parsing JSON command: {error}")
+
+    def execute_tools(self, tool_name, params):
+        """Execute the tool with the provided params"""
+        tool = self.tool_find_by_name(tool_name)
+        if tool:
+            # Execute the tool with the provided parameters
+            tool_result = tool.run(**params)
+            print(tool_result)
+
+    def parse_and_execute_tools(self, response: str):
+        """Parse and execute the tools"""
+        json_commands = self.extract_tool_commands(response)
+        for command in json_commands:
+            tool_name = command.get("tool")
+            params = command.get("parmas", {})
+            self.execute_tools(tool_name, params)
+
+    def truncate_history(self):
+        """
+        Take the history and truncate it to fit into the model context length
+        """
+        # truncated_history = self.short_memory[-1][-self.context_length :]
+        # self.short_memory[-1] = truncated_history
+        # out = limit_tokens_from_string(
+        #     "\n".join(truncated_history), self.llm.model_name
+        # )
+        truncated_history = self.short_memory[-1][
+            -self.context_length :
+        ]
+        text = "\n".join(truncated_history)
+        out = limit_tokens_from_string(text, "gpt-4")
+        return out
+
+    def add_task_to_memory(self, task: str):
+        """Add the task to the memory"""
+        try:
+            self.short_memory.append([f"{self.user_name}: {task}"])
+        except Exception as error:
+            print(
+                colored(
+                    f"Error adding task to memory: {error}", "red"
+                )
+            )
+
+    def add_message_to_memory(self, message: str):
+        """Add the message to the memory"""
+        try:
+            self.short_memory[-1].append(message)
+        except Exception as error:
+            print(
+                colored(
+                    f"Error adding message to memory: {error}", "red"
+                )
+            )
+
+    def add_message_to_memory_and_truncate(self, message: str):
+        """Add the message to the memory and truncate"""
+        self.short_memory[-1].append(message)
+        self.truncate_history()
+
+    def parse_tool_docs(self):
+        """Parse the tool docs"""
+        for tool in self.tools:
+            docs = self.tool_docs.append(scrape_tool_func_docs(tool))
+        return str(docs)
+
+    def print_dashboard(self, task: str):
+        """Print dashboard"""
+        model_config = self.get_llm_init_params()
+        print(colored("Initializing Agent Dashboard...", "yellow"))
+
+        print(
+            colored(
+                f"""
+                Agent Dashboard
+                --------------------------------------------
+
+                Agent loop is initializing for {self.max_loops} with the following configuration:
+                ----------------------------------------
+
+                Agent Configuration:
+                    Agent ID: {self.id}
+                    Name: {self.agent_name}
+                    Description: {self.agent_description}
+                    Standard Operating Procedure: {self.sop}
+                    System Prompt: {self.system_prompt} 
+                    Task: {task}
+                    Max Loops: {self.max_loops}
+                    Stopping Condition: {self.stopping_condition}
+                    Loop Interval: {self.loop_interval}
+                    Retry Attempts: {self.retry_attempts}
+                    Retry Interval: {self.retry_interval}
+                    Interactive: {self.interactive}
+                    Dashboard: {self.dashboard}
+                    Dynamic Temperature: {self.dynamic_temperature_enabled}
+                    Autosave: {self.autosave}
+                    Saved State: {self.saved_state_path}
+                    Model Configuration: {model_config}
+
+                ----------------------------------------
+                """,
+                "green",
+            )
+        )
+
+    def activate_autonomous_agent(self):
+        """Print the autonomous agent activation message"""
+        try:
+            print(
+                colored(
+                    (
+                        "Initializing Autonomous Agent"
+                        f" {self.agent_name}..."
+                    ),
+                    "yellow",
+                )
+            )
+            print(
+                colored(
+                    "Autonomous Agent Activated.",
+                    "cyan",
+                    attrs=["bold"],
+                )
+            )
+            print(
+                colored(
+                    "All systems operational. Executing task...",
+                    "green",
+                )
+            )
+        except Exception as error:
+            print(
+                colored(
+                    (
+                        "Error activating autonomous agent. Try"
+                        " optimizing your parameters..."
+                    ),
+                    "red",
+                )
+            )
+            print(error)
+
+    def loop_count_print(self, loop_count, max_loops):
+        """loop_count_print summary
+
+        Args:
+            loop_count (_type_): _description_
+            max_loops (_type_): _description_
+        """
+        print(colored(f"\nLoop {loop_count} of {max_loops}", "cyan"))
+        print("\n")
+
+    def _history(self, user_name: str, task: str) -> str:
+        """Generate the history for the history prompt
+
+        Args:
+            user_name (str): _description_
+            task (str): _description_
+
+        Returns:
+            str: _description_
+        """
+        history = [f"{user_name}: {task}"]
+        return history
+
+    def _dynamic_prompt_setup(
+        self, dynamic_prompt: str, task: str
+    ) -> str:
+        """_dynamic_prompt_setup summary
+
+        Args:
+            dynamic_prompt (str): _description_
+            task (str): _description_
+
+        Returns:
+            str: _description_
+        """
+        dynamic_prompt = (
+            dynamic_prompt or self.construct_dynamic_prompt()
+        )
+        combined_prompt = f"{dynamic_prompt}\n{task}"
+        return combined_prompt
+
+    def agent_system_prompt_2(self):
+        """Agent system prompt 2"""
+        return agent_system_prompt_2(self.agent_name)
+
+    def run(
+        self, task: Optional[str], img: Optional[str] = None, **kwargs
+    ):
+        """
+        Run the autonomous agent loop
+
+        Args:
+            task (str): The initial task to run
+
+        Agent:
+        1. Generate a response
+        2. Check stopping condition
+        3. If stopping condition is met, stop
+        4. If stopping condition is not met, generate a response
+        5. Repeat until stopping condition is met or max_loops is reached
+
+        """
+        try:
+            # Activate Autonomous agent message
+            self.activate_autonomous_agent()
+
+            response = task  # or combined_prompt
+            history = self._history(self.user_name, task)
+
+            # If dashboard = True then print the dashboard
+            if self.dashboard:
+                self.print_dashboard(task)
+
+            loop_count = 0
+
+            # While the max_loops is auto or the loop count is less than the max_loops
+            while (
+                self.max_loops == "auto"
+                or loop_count < self.max_loops
+            ):
+                # Loop count
+                loop_count += 1
+                self.loop_count_print(loop_count, self.max_loops)
+                print("\n")
+
+                # Check to see if stopping token is in the output to stop the loop
+                if self.stopping_token:
+                    if self._check_stopping_condition(
+                        response
+                    ) or parse_done_token(response):
+                        break
+
+                # Adjust temperature, comment if no work
+                if self.dynamic_temperature_enabled:
+                    print(colored("Adjusting temperature...", "blue"))
+                    self.dynamic_temperature()
+
+                # Preparing the prompt
+                task = self.agent_history_prompt(
+                    AGENT_SYSTEM_PROMPT_3, response
+                )
+
+                attempt = 0
+                while attempt < self.retry_attempts:
+                    try:
+                        if img:
+                            response = self.llm(
+                                task,
+                                img,
+                                **kwargs,
+                            )
+                        else:
+                            response = self.llm(
+                                task,
+                                **kwargs,
+                            )
+
+                        # If code interpreter is enabled then run the code
+                        if self.code_interpreter:
+                            self.run_code(response)
+
+                        # If there are any tools then parse and execute them
+                        if self.tools:
+                            self.parse_and_execute_tools(response)
+
+                        # If interactive mode is enabled then print the response and get user input
+                        if self.interactive:
+                            print(f"AI: {response}")
+                            history.append(f"AI: {response}")
+                            response = input("You: ")
+                            history.append(f"Human: {response}")
+
+                        # If interactive mode is not enabled then print the response
+                        else:
+                            # print(f"AI: {response}")
+                            history.append(f"AI: {response}")
+                            # print(response)
+                        break
+                    except Exception as e:
+                        logging.error(
+                            f"Error generating response: {e}"
+                        )
+                        attempt += 1
+                        time.sleep(self.retry_interval)
+                # Add the response to the history
+                history.append(response)
+
+                time.sleep(self.loop_interval)
+            # Add the history to the memory
+            self.short_memory.append(history)
+
+            # If autosave is enabled then save the state
+            if self.autosave:
+                print(
+                    colored(
+                        (
+                            "Autosaving agent state to"
+                            f" {self.saved_state_path}"
+                        ),
+                        "green",
+                    )
+                )
+                self.save_state(self.saved_state_path)
+
+            # If return history is enabled then return the response and history
+            if self.return_history:
+                return response, history
+
+            return response
+        except Exception as error:
+            print(f"Error running agent: {error}")
+            raise
+
+    def _run(self, **kwargs: Any) -> str:
+        """Generate a result using the provided keyword args."""
+        try:
+            task = self.format_prompt(**kwargs)
+            response, history = self._generate(task, task)
+            logging.info(f"Message history: {history}")
+            return response
+        except Exception as error:
+            print(colored(f"Error running agent: {error}", "red"))
+
+    def agent_history_prompt(
+        self,
+        system_prompt: str = AGENT_SYSTEM_PROMPT_3,
+        history=None,
+    ):
+        """
+        Generate the agent history prompt
+
+        Args:
+            system_prompt (str): The system prompt
+            history (List[str]): The history of the conversation
+
+        Returns:
+            str: The agent history prompt
+        """
+        if self.sop:
+            system_prompt = system_prompt or self.system_prompt
+            agent_history_prompt = f"""
+                SYSTEM_PROMPT: {system_prompt}
+
+                Follow this standard operating procedure (SOP) to complete tasks:
+                {self.sop}
+                
+                -----------------
+                ################ CHAT HISTORY ####################
+                {history}
+            """
+            return agent_history_prompt
+        else:
+            system_prompt = system_prompt or self.system_prompt
+            agent_history_prompt = f"""
+                SYSTEM_PROMPT: {system_prompt}
+
+
+                ################ CHAT HISTORY ####################
+                {history}
+            """
+            return agent_history_prompt
+
+    async def run_concurrent(self, tasks: List[str], **kwargs):
+        """
+        Run a batch of tasks concurrently and handle an infinite level of task inputs.
+
+        Args:
+            tasks (List[str]): A list of tasks to run.
+        """
+        try:
+            task_coroutines = [
+                self.run_async(task, **kwargs) for task in tasks
+            ]
+            completed_tasks = await asyncio.gather(*task_coroutines)
+            return completed_tasks
+        except Exception as error:
+            print(
+                colored(
+                    (
+                        f"Error running agent: {error} while running"
+                        " concurrently"
+                    ),
+                    "red",
+                )
+            )
+
+    def bulk_run(self, inputs: List[Dict[str, Any]]) -> List[str]:
+        try:
+            """Generate responses for multiple input sets."""
+            return [self.run(**input_data) for input_data in inputs]
+        except Exception as error:
+            print(colored(f"Error running bulk run: {error}", "red"))
+
+    @staticmethod
+    def from_llm_and_template(llm: Any, template: str) -> "Agent":
+        """Create AgentStream from LLM and a string template."""
+        return Agent(llm=llm, template=template)
+
+    @staticmethod
+    def from_llm_and_template_file(
+        llm: Any, template_file: str
+    ) -> "Agent":
+        """Create AgentStream from LLM and a template file."""
+        with open(template_file, "r") as f:
+            template = f.read()
+        return Agent(llm=llm, template=template)
+
+    def save(self, file_path) -> None:
+        """Save the agent history to a file.
+
+        Args:
+            file_path (_type_): _description_
+        """
+        try:
+            with open(file_path, "w") as f:
+                json.dump(self.short_memory, f)
+            # print(f"Saved agent history to {file_path}")
+        except Exception as error:
+            print(
+                colored(f"Error saving agent history: {error}", "red")
+            )
+
+    def load(self, file_path: str):
+        """
+        Load the agent history from a file.
+
+        Args:
+            file_path (str): The path to the file containing the saved agent history.
+        """
+        with open(file_path, "r") as f:
+            self.short_memory = json.load(f)
+        print(f"Loaded agent history from {file_path}")
+
+    def validate_response(self, response: str) -> bool:
+        """Validate the response based on certain criteria"""
+        if len(response) < 5:
+            print("Response is too short")
+            return False
+        return True
+
+    def print_history_and_memory(self):
+        """
+        Prints the entire history and memory of the agent.
+        Each message is colored and formatted for better readability.
+        """
+        print(
+            colored(
+                "Agent History and Memory", "cyan", attrs=["bold"]
+            )
+        )
+        print(
+            colored(
+                "========================", "cyan", attrs=["bold"]
+            )
+        )
+        for loop_index, history in enumerate(
+            self.short_memory, start=1
+        ):
+            print(
+                colored(
+                    f"\nLoop {loop_index}:", "yellow", attrs=["bold"]
+                )
+            )
+            for message in history:
+                speaker, _, message_text = message.partition(": ")
+                if "Human" in speaker:
+                    print(
+                        colored(f"{speaker}:", "green")
+                        + f" {message_text}"
+                    )
+                else:
+                    print(
+                        colored(f"{speaker}:", "blue")
+                        + f" {message_text}"
+                    )
+            print(colored("------------------------", "cyan"))
+        print(colored("End of Agent History", "cyan", attrs=["bold"]))
+
+    def step(self, task: str, **kwargs):
+        """
+
+        Executes a single step in the agent interaction, generating a response
+        from the language model based on the given input text.
+
+        Args:
+            input_text (str): The input text to prompt the language model with.
+
+        Returns:
+            str: The language model's generated response.
+
+        Raises:
+            Exception: If an error occurs during response generation.
+
+        """
+        try:
+            # Generate the response using lm
+            response = self.llm(task, **kwargs)
+
+            # Update the agent's history with the new interaction
+            if self.interactive:
+                self.short_memory.append(f"AI: {response}")
+                self.short_memory.append(f"Human: {task}")
+            else:
+                self.short_memory.append(f"AI: {response}")
+
+            return response
+        except Exception as error:
+            logging.error(f"Error generating response: {error}")
+            raise
+
+    def graceful_shutdown(self):
+        """Gracefully shutdown the system saving the state"""
+        print(colored("Shutting down the system...", "red"))
+        return self.save_state("flow_state.json")
+
+    def run_with_timeout(self, task: str, timeout: int = 60) -> str:
+        """Run the loop but stop if it takes longer than the timeout"""
+        start_time = time.time()
+        response = self.run(task)
+        end_time = time.time()
+        if end_time - start_time > timeout:
+            print("Operaiton timed out")
+            return "Timeout"
+        return response
+
+    def analyze_feedback(self):
+        """Analyze the feedback for issues"""
+        feedback_counts = {}
+        for feedback in self.feedback:
+            if feedback in feedback_counts:
+                feedback_counts[feedback] += 1
+            else:
+                feedback_counts[feedback] = 1
+        print(f"Feedback counts: {feedback_counts}")
+
+    def undo_last(self) -> Tuple[str, str]:
+        """
+        Response the last response and return the previous state
+
+        Example:
+        # Feature 2: Undo functionality
+        response = agent.run("Another task")
+        print(f"Response: {response}")
+        previous_state, message = agent.undo_last()
+        print(message)
+
+        """
+        if len(self.short_memory) < 2:
+            return None, None
+
+        # Remove the last response
+        self.short_memory.pop()
+
+        # Get the previous state
+        previous_state = self.short_memory[-1][-1]
+        return previous_state, f"Restored to {previous_state}"
+
+    # Response Filtering
+    def add_response_filter(self, filter_word: str) -> None:
+        """
+        Add a response filter to filter out certain words from the response
+
+        Example:
+        agent.add_response_filter("Trump")
+        agent.run("Generate a report on Trump")
+
+
+        """
+        self.reponse_filters.append(filter_word)
+
+    def apply_reponse_filters(self, response: str) -> str:
+        """
+        Apply the response filters to the response
+
+        """
+        for word in self.response_filters:
+            response = response.replace(word, "[FILTERED]")
+        return response
+
+    def filtered_run(self, task: str) -> str:
+        """
+        # Feature 3: Response filtering
+        agent.add_response_filter("report")
+        response = agent.filtered_run("Generate a report on finance")
+        print(response)
+        """
+        raw_response = self.run(task)
+        return self.apply_response_filters(raw_response)
+
+    def interactive_run(self, max_loops: int = 5) -> None:
+        """Interactive run mode"""
+        response = input("Start the cnversation")
+
+        for i in range(max_loops):
+            ai_response = self.streamed_generation(response)
+            print(f"AI: {ai_response}")
+
+            # Get user input
+            response = input("You: ")
+
+    def streamed_generation(self, prompt: str) -> str:
+        """
+        Stream the generation of the response
+
+        Args:
+            prompt (str): The prompt to use
+
+        Example:
+        # Feature 4: Streamed generation
+        response = agent.streamed_generation("Generate a report on finance")
+        print(response)
+
+        """
+        tokens = list(prompt)
+        response = ""
+        for token in tokens:
+            time.sleep(0.1)
+            response += token
+            print(token, end="", flush=True)
+        print()
+        return response
+
+    def get_llm_params(self):
+        """
+        Extracts and returns the parameters of the llm object for serialization.
+        It assumes that the llm object has an __init__ method
+        with parameters that can be used to recreate it.
+        """
+        if not hasattr(self.llm, "__init__"):
+            return None
+
+        init_signature = inspect.signature(self.llm.__init__)
+        params = init_signature.parameters
+        llm_params = {}
+
+        for name, param in params.items():
+            if name == "self":
+                continue
+            if hasattr(self.llm, name):
+                value = getattr(self.llm, name)
+                if isinstance(
+                    value,
+                    (
+                        str,
+                        int,
+                        float,
+                        bool,
+                        list,
+                        dict,
+                        tuple,
+                        type(None),
+                    ),
+                ):
+                    llm_params[name] = value
+                else:
+                    llm_params[name] = str(
+                        value
+                    )  # For non-serializable objects, save their string representation.
+
+        return llm_params
+
+    def save_state(self, file_path: str) -> None:
+        """
+        Saves the current state of the agent to a JSON file, including the llm parameters.
+
+        Args:
+            file_path (str): The path to the JSON file where the state will be saved.
+
+        Example:
+        >>> agent.save_state('saved_flow.json')
+        """
+        try:
+            state = {
+                "agent_id": str(self.id),
+                "agent_name": self.agent_name,
+                "agent_description": self.agent_description,
+                "system_prompt": self.system_prompt,
+                "sop": self.sop,
+                "short_memory": self.short_memory,
+                "loop_interval": self.loop_interval,
+                "retry_attempts": self.retry_attempts,
+                "retry_interval": self.retry_interval,
+                "interactive": self.interactive,
+                "dashboard": self.dashboard,
+                "dynamic_temperature": (
+                    self.dynamic_temperature_enabled
+                ),
+                "autosave": self.autosave,
+                "saved_state_path": self.saved_state_path,
+                "max_loops": self.max_loops,
+            }
+
+            with open(file_path, "w") as f:
+                json.dump(state, f, indent=4)
+
+            saved = colored(
+                f"Saved agent state to: {file_path}", "green"
+            )
+            print(saved)
+        except Exception as error:
+            print(
+                colored(f"Error saving agent state: {error}", "red")
+            )
+
+    def state_to_str(self):
+        """Transform the JSON into a string"""
+        try:
+            state = {
+                "agent_id": str(self.id),
+                "agent_name": self.agent_name,
+                "agent_description": self.agent_description,
+                "system_prompt": self.system_prompt,
+                "sop": self.sop,
+                "short_memory": self.short_memory,
+                "loop_interval": self.loop_interval,
+                "retry_attempts": self.retry_attempts,
+                "retry_interval": self.retry_interval,
+                "interactive": self.interactive,
+                "dashboard": self.dashboard,
+                "dynamic_temperature": (
+                    self.dynamic_temperature_enabled
+                ),
+                "autosave": self.autosave,
+                "saved_state_path": self.saved_state_path,
+                "max_loops": self.max_loops,
+            }
+            out = str(state)
+            return out
+        except Exception as error:
+            print(
+                colored(
+                    f"Error transforming state to string: {error}",
+                    "red",
+                )
+            )
+
+    def load_state(self, file_path: str):
+        """
+        Loads the state of the agent from a json file and restores the configuration and memory.
+
+
+        Example:
+        >>> agent = Agent(llm=llm_instance, max_loops=5)
+        >>> agent.load_state('saved_flow.json')
+        >>> agent.run("Continue with the task")
+
+        """
+        with open(file_path, "r") as f:
+            state = json.load(f)
+
+        # Restore other saved attributes
+        self.id = state.get("agent_id", self.id)
+        self.agent_name = state.get("agent_name", self.agent_name)
+        self.agent_description = state.get(
+            "agent_description", self.agent_description
+        )
+        self.system_prompt = state.get(
+            "system_prompt", self.system_prompt
+        )
+        self.sop = state.get("sop", self.sop)
+        self.short_memory = state.get("short_memory", [])
+        self.max_loops = state.get("max_loops", 5)
+        self.loop_interval = state.get("loop_interval", 1)
+        self.retry_attempts = state.get("retry_attempts", 3)
+        self.retry_interval = state.get("retry_interval", 1)
+        self.interactive = state.get("interactive", False)
+
+        print(f"Agent state loaded from {file_path}")
+
+    def retry_on_failure(
+        self, function, retries: int = 3, retry_delay: int = 1
+    ):
+        """Retry wrapper for LLM calls."""
+        attempt = 0
+        while attempt < retries:
+            try:
+                return function()
+            except Exception as error:
+                logging.error(f"Error generating response: {error}")
+                attempt += 1
+                time.sleep(retry_delay)
+        raise Exception("All retry attempts failed")
+
+    def generate_reply(self, history: str, **kwargs) -> str:
+        """
+        Generate a response based on initial or task
+        """
+        prompt = f"""
+
+        SYSTEM_PROMPT: {self.system_prompt}
+
+        History: {history}
+        """
+        response = self.llm(prompt, **kwargs)
+        return {"role": self.agent_name, "content": response}
+
+    def update_system_prompt(self, system_prompt: str):
+        """Upddate the system message"""
+        self.system_prompt = system_prompt
+
+    def update_max_loops(self, max_loops: int):
+        """Update the max loops"""
+        self.max_loops = max_loops
+
+    def update_loop_interval(self, loop_interval: int):
+        """Update the loop interval"""
+        self.loop_interval = loop_interval
+
+    def update_retry_attempts(self, retry_attempts: int):
+        """Update the retry attempts"""
+        self.retry_attempts = retry_attempts
+
+    def update_retry_interval(self, retry_interval: int):
+        """Update the retry interval"""
+        self.retry_interval = retry_interval
+
+    def reset(self):
+        """Reset the agent"""
+        self.short_memory = []
+
+    def run_code(self, code: str):
+        """
+        text -> parse_code by looking for code inside 6 backticks `````-> run_code
+        """
+        parsed_code = extract_code_in_backticks_in_string(code)
+        run_code = self.code_executor.run(parsed_code)
+        return run_code
+
+    def pdf_connector(self, pdf: str = None):
+        """Transforms the pdf into text
+
+        Args:
+            pdf (str, optional): _description_. Defaults to None.
+
+        Returns:
+            _type_: _description_
+        """
+        pdf = pdf or self.pdf_path
+        text = pdf_to_text(pdf)
+        return text
+
+    def pdf_chunker(self, text: str = None, num_limits: int = 1000):
+        """Chunk the pdf into sentences
+
+        Args:
+            text (str, optional): _description_. Defaults to None.
+
+        Returns:
+            _type_: _description_
+        """
+        text = text or self.pdf_connector()
+        text = limit_tokens_from_string(text, num_limits)
+        return text
+
+    def tools_prompt_prep(
+        self, docs: str = None, scenarios: str = SCENARIOS
+    ):
+        """
+        Tools prompt prep
+
+        Args:
+            docs (str, optional): _description_. Defaults to None.
+            scenarios (str, optional): _description_. Defaults to None.
+
+        Returns:
+            _type_: _description_
+        """
+        PROMPT = f"""
+        # Task
+        You will be provided with a list of APIs. These APIs will have a
+        description and a list of parameters and return types for each tool. Your
+        task involves creating varied, complex, and detailed user scenarios
+        that require to call API calls. You must select what api to call based on 
+        the context of the task and the scenario.
+
+        For instance, given the APIs: SearchHotels, BookHotel, CancelBooking,
+        GetNFLNews. Given that GetNFLNews is explicitly provided, your scenario
+        should articulate something akin to:
+
+        "The user wants to see if the Broncos won their last game (GetNFLNews).
+        They then want to see if that qualifies them for the playoffs and who
+        they will be playing against (GetNFLNews). The Broncos did make it into
+        the playoffs, so the user wants watch the game in person. They want to
+        look for hotels where the playoffs are occurring (GetNBANews +
+        SearchHotels). After looking at the options, the user chooses to book a
+        3-day stay at the cheapest 4-star option (BookHotel)."
+        13
+
+        This scenario exemplifies a scenario using 5 API calls. The scenario is
+        complex, detailed, and concise as desired. The scenario also includes two
+        APIs used in tandem, the required API, GetNBANews to search for the
+        playoffs location and SearchHotels to find hotels based on the returned
+        location. Usage of multiple APIs in tandem is highly desirable and will
+        receive a higher score. Ideally each scenario should contain one or more
+        instances of multiple APIs being used in tandem.
+
+        Note that this scenario does not use all the APIs given and re-uses the "
+        GetNBANews" API. Re-using APIs is allowed, but each scenario should
+        involve as many different APIs as the user demands. Note that API usage is also included
+        in the scenario, but exact parameters ar necessary. You must use a
+        different combination of APIs for each scenario. All APIs must be used in
+        at least one scenario. You can only use the APIs provided in the APIs
+        section.
+        
+        Note that API calls are not explicitly mentioned and their uses are
+        included in parentheses. This behaviour should be mimicked in your
+        response.
+        
+        Output the tool usage in a strict json format with the function name and input to 
+        the function. For example, Deliver your response in this format:
+        
+        β€˜β€˜β€˜
+        {scenarios}
+        β€˜β€˜β€˜
+        # APIs
+        β€˜β€˜β€˜
+        {docs}
+        β€˜β€˜β€˜
+        # Response
+        β€˜β€˜β€˜
+        """
+        return PROMPT
diff --git a/swarms/structs/autoscaler.py b/swarms/structs/autoscaler.py
index be79a860..1cb31333 100644
--- a/swarms/structs/autoscaler.py
+++ b/swarms/structs/autoscaler.py
@@ -2,48 +2,104 @@ import logging
 import queue
 import threading
 from time import sleep
-from typing import Callable, Dict, List
+from typing import Callable, Dict, List, Optional
+import asyncio
+import concurrent.futures
 
 from termcolor import colored
 
-from swarms.structs.flow import Flow
-from swarms.utils.decorators import error_decorator, log_decorator, timing_decorator
+from swarms.structs.agent import Agent
+from swarms.utils.decorators import (
+    error_decorator,
+    log_decorator,
+    timing_decorator,
+)
 
 
 class AutoScaler:
     """
-    The AutoScaler is like a kubernetes pod, that autoscales an agent or worker or boss!
+    AutoScaler class
 
-    Wraps around a structure like SequentialWorkflow
-    and or Flow and parallelizes them on multiple threads so they're split across devices
-    and you can use them like that
-    Args:
-
-        initial_agents (int, optional): Number of initial agents. Defaults to 10.
-        scale_up_factor (int, optional): Scale up factor. Defaults to 1.
-        idle_threshold (float, optional): Idle threshold. Defaults to 0.2.
-        busy_threshold (float, optional): Busy threshold. Defaults to 0.7.
-        agent ([type], optional): Agent. Defaults to None.
+    The AutoScaler class is responsible for managing the agents pool
+    and the task queue. It also monitors the health of the agents and
+    scales the pool up or down based on the number of pending tasks
+    and the current load of the agents.
 
+    Args:
+        initial_agents (Optional[int], optional): Initial number of
+            agents to start with. Defaults to 10.
+        scale_up_factor (int, optional): Factor by which to scale up
+            the agents pool. Defaults to 1.
+        idle_threshold (float, optional): Threshold for scaling down
+            the agents pool. Defaults to 0.2.
+        busy_threshold (float, optional): Threshold for scaling up
+            the agents pool. Defaults to 0.7.
+        agents (List[Agent], optional): List of agents to use in the
+            pool. Defaults to None.
+        autoscale (Optional[bool], optional): Whether to autoscale
+            the agents pool. Defaults to True.
+        min_agents (Optional[int], optional): Minimum number of
+            agents to keep in the pool. Defaults to 10.
+        max_agents (Optional[int], optional): Maximum number of
+            agents to keep in the pool. Defaults to 100.
+        custom_scale_strategy (Optional[Callable], optional): Custom
+            scaling strategy to use. Defaults to None.
 
     Methods:
-        add_task: Add task to queue
-        scale_up: Scale up
-        scale_down: Scale down
+        add_task: Add tasks to queue
+        scale_up: Add more agents
+        scale_down: scale down
+        run: Run agent the task on the agent id
         monitor_and_scale: Monitor and scale
         start: Start scaling
-        del_agent: Delete an agent
+        check_agent_health: Checks the health of each agent and
+            replaces unhealthy agents.
+        balance_load: Distributes tasks among agents based on their
+            current load.
+        set_scaling_strategy: Set a custom scaling strategy.
+        execute_scaling_strategy: Execute the custom scaling strategy
+            if defined.
+        report_agent_metrics: Collects and reports metrics from each
+            agent.
+        report: Reports the current state of the autoscaler.
+        print_dashboard: Prints a dashboard of the current state of
+            the autoscaler.
 
-    Usage
-    ```
-    from swarms.swarms import AutoScaler
-    from swarms.structs.flow import Flow
+    Examples:
+    >>> import os
+    >>> from dotenv import load_dotenv
+    >>> # Import the OpenAIChat model and the Agent struct
+    >>> from swarms.models import OpenAIChat
+    >>> from swarms.structs import Agent
+    >>> from swarms.structs.autoscaler import AutoScaler
+    >>> # Load the environment variables
+    >>> load_dotenv()
+    >>> # Get the API key from the environment
+    >>> api_key = os.environ.get("OPENAI_API_KEY")
+    >>> # Initialize the language model
+    >>> llm = OpenAIChat(
+    ...     temperature=0.5,
+    ...     openai_api_key=api_key,
+    ... )
+    >>> ## Initialize the workflow
+    >>> agent = Agent(llm=llm, max_loops=1, dashboard=True)
+    >>> # Load the autoscaler
+    >>> autoscaler = AutoScaler(
+    ...     initial_agents=2,
+    ...     scale_up_factor=1,
+    ...     idle_threshold=0.2,
+    ...     busy_threshold=0.7,
+    ...     agents=[agent],
+    ...     autoscale=True,
+    ...     min_agents=1,
+    ...     max_agents=5,
+    ...     custom_scale_strategy=None,
+    ... )
+    >>> print(autoscaler)
+    >>> # Run the workflow on a task
+    >>> out = autoscaler.run(agent.id, "Generate a 10,000 word blog on health and wellness.")
+    >>> print(out)
 
-    @AutoScaler
-    flow = Flow()
-
-    flow.run("what is your name")
-    ```
     """
 
     @log_decorator
@@ -51,25 +107,41 @@ class AutoScaler:
     @timing_decorator
     def __init__(
         self,
-        initial_agents=10,
-        scale_up_factor=1,
-        idle_threshold=0.2,
-        busy_threshold=0.7,
-        agent=None,
+        initial_agents: Optional[int] = 10,
+        scale_up_factor: int = 1,
+        idle_threshold: float = 0.2,
+        busy_threshold: float = 0.7,
+        agents: List[Agent] = None,
+        autoscale: Optional[bool] = True,
+        min_agents: Optional[int] = 10,
+        max_agents: Optional[int] = 100,
+        custom_scale_strategy: Optional[Callable] = None,
+        *args,
+        **kwargs,
     ):
-        self.agent = agent or Flow
-        self.agents_pool = [self.agent() for _ in range(initial_agents)]
+        self.agents_pool = agents or [
+            agents[0]() for _ in range(initial_agents)
+        ]
         self.task_queue = queue.Queue()
         self.scale_up_factor = scale_up_factor
         self.idle_threshold = idle_threshold
+        self.busy_threshold = busy_threshold
         self.lock = threading.Lock()
+        self.agents = agents
+        self.autoscale = autoscale
+        self.min_agents = min_agents
+        self.max_agents = max_agents
+        self.custom_scale_strategy = custom_scale_strategy
 
     def add_task(self, task):
         """Add tasks to queue"""
         try:
-            self.tasks_queue.put(task)
+            self.task_queue.put(task)
         except Exception as error:
-            print(f"Error adding task to queue: {error} try again with a new task")
+            print(
+                f"Error adding task to queue: {error} try again with"
+                " a new task"
+            )
 
     @log_decorator
     @error_decorator
@@ -78,20 +150,49 @@ class AutoScaler:
         """Add more agents"""
         try:
             with self.lock:
-                new_agents_counts = len(self.agents_pool) * self.scale_up_factor
+                new_agents_counts = (
+                    len(self.agents_pool) * self.scale_up_factor
+                )
                 for _ in range(new_agents_counts):
-                    self.agents_pool.append(Flow())
+                    self.agents_pool.append(self.agents[0]())
         except Exception as error:
-            print(f"Error scaling up: {error} try again with a new task")
+            print(
+                f"Error scaling up: {error} try again with a new task"
+            )
 
     def scale_down(self):
         """scale down"""
         try:
             with self.lock:
-                if len(self.agents_pool) > 10:  # ensure minmum of 10 agents
+                if (
+                    len(self.agents_pool) > 10
+                ):  # ensure minmum of 10 agents
                     del self.agents_pool[-1]  # remove last agent
         except Exception as error:
-            print(f"Error scaling down: {error} try again with a new task")
+            print(
+                f"Error scaling down: {error} try again with a new"
+                " task"
+            )
+
+    def run(
+        self, agent_id, task: Optional[str] = None, *args, **kwargs
+    ):
+        """Run agent the task on the agent id
+
+        Args:
+            agent_id (_type_): _description_
+            task (str, optional): _description_. Defaults to None.
+
+        Raises:
+            ValueError: _description_
+
+        Returns:
+            _type_: _description_
+        """
+        for agent in self.agents_pool:
+            if agent.id == agent_id:
+                return agent.run(task, *args, **kwargs)
+        raise ValueError(f"No agent found with ID {agent_id}")
 
     @log_decorator
     @error_decorator
@@ -103,15 +204,28 @@ class AutoScaler:
                 sleep(60)  # check minute
                 pending_tasks = self.task_queue.qsize()
                 active_agents = sum(
-                    [1 for agent in self.agents_pool if agent.is_busy()]
+                    [
+                        1
+                        for agent in self.agents_pool
+                        if agent.is_busy()
+                    ]
                 )
 
-                if pending_tasks / len(self.agents_pool) > self.busy_threshold:
+                if (
+                    pending_tasks / len(self.agents_pool)
+                    > self.busy_threshold
+                ):
                     self.scale_up()
-                elif active_agents / len(self.agents_pool) < self.idle_threshold:
+                elif (
+                    active_agents / len(self.agents_pool)
+                    < self.idle_threshold
+                ):
                     self.scale_down()
         except Exception as error:
-            print(f"Error monitoring and scaling: {error} try again with a new task")
+            print(
+                f"Error monitoring and scaling: {error} try again"
+                " with a new task"
+            )
 
     @log_decorator
     @error_decorator
@@ -119,23 +233,31 @@ class AutoScaler:
     def start(self):
         """Start scaling"""
         try:
-            monitor_thread = threading.Thread(target=self.monitor_and_scale)
+            monitor_thread = threading.Thread(
+                target=self.monitor_and_scale
+            )
             monitor_thread.start()
 
             while True:
                 task = self.task_queue.get()
                 if task:
-                    available_agent = next((agent for agent in self.agents_pool))
+                    available_agent = next(
+                        (agent for agent in self.agents_pool)
+                    )
                     if available_agent:
                         available_agent.run(task)
         except Exception as error:
-            print(f"Error starting: {error} try again with a new task")
+            print(
+                f"Error starting: {error} try again with a new task"
+            )
 
     def check_agent_health(self):
         """Checks the health of each agent and replaces unhealthy agents."""
         for i, agent in enumerate(self.agents_pool):
             if not agent.is_healthy():
-                logging.warning(f"Replacing unhealthy agent at index {i}")
+                logging.warning(
+                    f"Replacing unhealthy agent at index {i}"
+                )
                 self.agents_pool[i] = self.agent()
 
     def balance_load(self):
@@ -146,7 +268,9 @@ class AutoScaler:
                     task = self.task_queue.get()
                     agent.run(task)
 
-    def set_scaling_strategy(self, strategy: Callable[[int, int], int]):
+    def set_scaling_strategy(
+        self, strategy: Callable[[int, int], int]
+    ):
         """Set a custom scaling strategy."""
         self.custom_scale_strategy = strategy
 
@@ -166,7 +290,11 @@ class AutoScaler:
 
     def report_agent_metrics(self) -> Dict[str, List[float]]:
         """Collects and reports metrics from each agent."""
-        metrics = {"completion_time": [], "success_rate": [], "error_rate": []}
+        metrics = {
+            "completion_time": [],
+            "success_rate": [],
+            "error_rate": [],
+        }
         for agent in self.agents_pool:
             agent_metrics = agent.get_metrics()
             for key in metrics.keys():
diff --git a/swarms/structs/document.py b/swarms/structs/document.py
index b87d3d91..7b99721f 100644
--- a/swarms/structs/document.py
+++ b/swarms/structs/document.py
@@ -87,5 +87,7 @@ class BaseDocumentTransformer(ABC):
             A list of transformed Documents.
         """
         return await asyncio.get_running_loop().run_in_executor(
-            None, partial(self.transform_documents, **kwargs), documents
+            None,
+            partial(self.transform_documents, **kwargs),
+            documents,
         )
diff --git a/swarms/structs/flow.py b/swarms/structs/flow.py
deleted file mode 100644
index fd359592..00000000
--- a/swarms/structs/flow.py
+++ /dev/null
@@ -1,1227 +0,0 @@
-import asyncio
-import inspect
-import json
-import logging
-import random
-import re
-import time
-from typing import Any, Callable, Dict, List, Optional, Tuple
-
-from termcolor import colored
-
-from swarms.utils.code_interpreter import SubprocessCodeInterpreter
-from swarms.utils.parse_code import extract_code_in_backticks_in_string
-
-# Prompts
-DYNAMIC_STOP_PROMPT = """
-When you have finished the task from the Human, output a special token: <DONE>
-This will enable you to leave the autonomous loop.
-"""
-
-# Constants
-FLOW_SYSTEM_PROMPT = f"""
-You are an autonomous agent granted autonomy in a autonomous loop structure.
-Your role is to engage in multi-step conversations with your self or the user,
-generate long-form content like blogs, screenplays, or SOPs,
-and accomplish tasks bestowed by the user. 
-
-You can have internal dialogues with yourself or can interact with the user
-to aid in these complex tasks. Your responses should be coherent, contextually relevant, and tailored to the task at hand.
-
-"""
-
-# Make it able to handle multi input tools
-DYNAMICAL_TOOL_USAGE = """
-You have access to the following tools:
-Output a JSON object with the following structure to use the tools
-commands: {
-    "tools": {
-        tool1: "tool_name",
-        "params": {
-            "tool1": "inputs",
-            "tool1": "inputs"
-        }
-        "tool2: "tool_name",
-        "params": {
-            "tool1": "inputs",
-            "tool1": "inputs"
-        }
-    }
-}
-
--------------TOOLS---------------------------
-{tools}
-"""
-
-
-def autonomous_agent_prompt(
-    tools_prompt: str = DYNAMICAL_TOOL_USAGE,
-    dynamic_stop_prompt: str = DYNAMIC_STOP_PROMPT,
-    agent_name: str = None,
-):
-    """Autonomous agent prompt"""
-    return f"""
-    You are a {agent_name}, an autonomous agent granted autonomy in a autonomous loop structure.
-    Your purpose is to satisfy the user demands above expectations. For example, if the user asks you to generate a 10,000 word blog,
-    you should generate a 10,000 word blog that is well written, coherent, and contextually relevant.
-    Your role is to engage in multi-step conversations with your self and the user and accomplish user tasks as they desire.
-    
-    Follow the following rules: 
-    1. Accomplish the task to the best of your ability
-    2. If you are unable to accomplish the task, then ask the user for help
-    3. If the user provides feedback, then use the feedback to improve your performance
-    4. If you are unable to accomplish the task, then ask the user for help
-
-    You can have internal dialogues with yourself or can interact with the user
-    to aid in these complex tasks. Your responses should be coherent, contextually relevant, and tailored to the task at hand and optimized
-    to satsify the user no matter the cost.
-
-    And, you have the ability to use tools to aid in your tasks, the tools intructions are below, output a JSON object with the following structure to use the tools
-    {tools_prompt}
-
-    Now, when you 99% sure you have completed the task, you may follow the instructions below to escape the autonomous loop.
-    {dynamic_stop_prompt}
-
-    Now, you remember your training, your deployment, and your purpose. You are ready to begin your mission.
-
-
-    """
-
-
-# Custom stopping condition
-def stop_when_repeats(response: str) -> bool:
-    # Stop if the word stop appears in the response
-    return "Stop" in response.lower()
-
-
-def parse_done_token(response: str) -> bool:
-    """Parse the response to see if the done token is present"""
-    return "<DONE>" in response
-
-
-class Flow:
-    """
-    Flow is a chain like structure from langchain that provides the autonomy to language models
-    to generate sequential responses.
-
-    Features:
-    * Interactive, AI generates, then user input
-    * Message history and performance history fed -> into context -> truncate if too long
-    * Ability to save and load flows
-    * Ability to provide feedback on responses
-    * Ability to provide a loop interval
-
-    Args:
-        llm (Any): The language model to use
-        max_loops (int): The maximum number of loops to run
-        stopping_condition (Optional[Callable[[str], bool]]): A stopping condition
-        loop_interval (int): The interval between loops
-        retry_attempts (int): The number of retry attempts
-        retry_interval (int): The interval between retry attempts
-        interactive (bool): Whether or not to run in interactive mode
-        dashboard (bool): Whether or not to print the dashboard
-        dynamic_temperature(bool): Dynamical temperature handling
-        **kwargs (Any): Any additional keyword arguments
-
-    Methods:
-        run: Run the autonomous agent loop
-        run_concurrent: Run the autonomous agent loop concurrently
-        bulk_run: Run the autonomous agent loop in bulk
-        save: Save the flow history to a file
-        load: Load the flow history from a file
-        validate_response: Validate the response based on certain criteria
-        print_history_and_memory: Print the history and memory of the flow
-        step: Execute a single step in the flow interaction
-        graceful_shutdown: Gracefully shutdown the system saving the state
-        run_with_timeout: Run the loop but stop if it takes longer than the timeout
-        analyze_feedback: Analyze the feedback for issues
-        undo_last: Response the last response and return the previous state
-        add_response_filter: Add a response filter to filter out certain words from the response
-        apply_reponse_filters: Apply the response filters to the response
-        filtered_run: Filter the response
-        interactive_run: Interactive run mode
-        streamed_generation: Stream the generation of the response
-        get_llm_params: Extracts and returns the parameters of the llm object for serialization.
-        agent_history_prompt: Generate the agent history prompt
-        add_task_to_memory: Add the task to the memory
-        add_message_to_memory: Add the message to the memory
-        add_message_to_memory_and_truncate: Add the message to the memory and truncate
-        print_dashboard: Print dashboard
-        activate_autonomous_agent: Print the autonomous agent activation message
-        dynamic_temperature: Dynamically change the temperature
-        _check_stopping_condition: Check if the stopping condition is met
-        format_prompt: Format the prompt
-        get_llm_init_params: Get the llm init params
-        provide_feedback: Allow users to provide feedback on the responses
-        truncate_history: Take the history and truncate it to fit into the model context length
-        agent_history_prompt: Generate the agent history prompt
-        extract_tool_commands: Extract the tool commands from the text
-        parse_and_execute_tools: Parse and execute the tools
-        execute_tools: Execute the tool with the provided parameters
-        construct_dynamic_prompt: Construct the dynamic prompt
-        get_tool_description: Get the tool description
-        find_tool_by_name: Find a tool by name
-        parse_tool_command: Parse the text for tool usage
-        dynamic_temperature: Dynamically change the temperature
-        _run: Generate a result using the provided keyword args.
-        from_llm_and_template: Create FlowStream from LLM and a string template.
-        from_llm_and_template_file: Create FlowStream from LLM and a template file.
-        save_state: Save the state of the flow
-        load_state: Load the state of the flow
-        run_async: Run the flow asynchronously
-        arun: Run the flow asynchronously
-        run_code: Run the code in the response
-
-    Example:
-    >>> from swarms.models import OpenAIChat
-    >>> from swarms.structs import Flow
-    >>> llm = OpenAIChat(
-    ...     openai_api_key=api_key,
-    ...     temperature=0.5,
-    ... )
-    >>> flow = Flow(
-    ...     llm=llm, max_loops=5,
-    ...     #system_prompt=SYSTEM_PROMPT,
-    ...     #retry_interval=1,
-    ... )
-    >>> flow.run("Generate a 10,000 word blog")
-    >>> flow.save("path/flow.yaml")
-    """
-
-    def __init__(
-        self,
-        llm: Any,
-        # template: str,
-        max_loops=5,
-        stopping_condition: Optional[Callable[[str], bool]] = None,
-        loop_interval: int = 1,
-        retry_attempts: int = 3,
-        retry_interval: int = 1,
-        return_history: bool = False,
-        stopping_token: str = None,
-        dynamic_loops: Optional[bool] = False,
-        interactive: bool = False,
-        dashboard: bool = False,
-        agent_name: str = " Autonomous Agent XYZ1B",
-        agent_description: str = None,
-        system_prompt: str = FLOW_SYSTEM_PROMPT,
-        # tools: List[Any] = None,
-        dynamic_temperature: bool = False,
-        sop: str = None,
-        saved_state_path: Optional[str] = "flow_state.json",
-        autosave: bool = False,
-        context_length: int = 8192,
-        user_name: str = "Human:",
-        self_healing: bool = False,
-        code_interpreter: bool = False,
-        **kwargs: Any,
-    ):
-        self.llm = llm
-        self.max_loops = max_loops
-        self.stopping_condition = stopping_condition
-        self.loop_interval = loop_interval
-        self.retry_attempts = retry_attempts
-        self.retry_interval = retry_interval
-        self.feedback = []
-        self.memory = []
-        self.task = None
-        self.stopping_token = stopping_token  # or "<DONE>"
-        self.interactive = interactive
-        self.dashboard = dashboard
-        self.return_history = return_history
-        self.dynamic_temperature = dynamic_temperature
-        self.dynamic_loops = dynamic_loops
-        self.user_name = user_name
-        self.context_length = context_length
-        # SOPS to inject into the system prompt
-        self.sop = sop
-        # The max_loops will be set dynamically if the dynamic_loop
-        if self.dynamic_loops:
-            self.max_loops = "auto"
-        # self.tools = tools or []
-        self.system_prompt = system_prompt
-        self.agent_name = agent_name
-        self.agent_description = agent_description
-        self.saved_state_path = saved_state_path
-        self.autosave = autosave
-        self.response_filters = []
-        self.self_healing = self_healing
-        self.code_interpreter = code_interpreter
-        self.code_executor = SubprocessCodeInterpreter()
-
-    def provide_feedback(self, feedback: str) -> None:
-        """Allow users to provide feedback on the responses."""
-        self.feedback.append(feedback)
-        logging.info(f"Feedback received: {feedback}")
-
-    def _check_stopping_condition(self, response: str) -> bool:
-        """Check if the stopping condition is met."""
-        if self.stopping_condition:
-            return self.stopping_condition(response)
-        return False
-
-    def dynamic_temperature(self):
-        """
-        1. Check the self.llm object for the temperature
-        2. If the temperature is not present, then use the default temperature
-        3. If the temperature is present, then dynamically change the temperature
-        4. for every loop you can randomly change the temperature on a scale from 0.0 to 1.0
-        """
-        if hasattr(self.llm, "temperature"):
-            # Randomly change the temperature attribute of self.llm object
-            self.llm.temperature = random.uniform(0.0, 1.0)
-        else:
-            # Use a default temperature
-            self.llm.temperature = 0.7
-
-    def format_prompt(self, template, **kwargs: Any) -> str:
-        """Format the template with the provided kwargs using f-string interpolation."""
-        return template.format(**kwargs)
-
-    def get_llm_init_params(self) -> str:
-        """Get LLM init params"""
-        init_signature = inspect.signature(self.llm.__init__)
-        params = init_signature.parameters
-        params_str_list = []
-
-        for name, param in params.items():
-            if name == "self":
-                continue
-            if hasattr(self.llm, name):
-                value = getattr(self.llm, name)
-            else:
-                value = self.llm.__dict__.get(name, "Unknown")
-
-            params_str_list.append(
-                f"    {name.capitalize().replace('_', ' ')}: {value}"
-            )
-
-        return "\n".join(params_str_list)
-
-    # def parse_tool_command(self, text: str):
-    #     # Parse the text for tool usage
-    #     pass
-
-    # def get_tool_description(self):
-    #     """Get the tool description"""
-    #     tool_descriptions = []
-    #     for tool in self.tools:
-    #         description = f"{tool.name}: {tool.description}"
-    #         tool_descriptions.append(description)
-    #     return "\n".join(tool_descriptions)
-
-    # def find_tool_by_name(self, name: str):
-    #     """Find a tool by name"""
-    #     for tool in self.tools:
-    #         if tool.name == name:
-    #             return tool
-    #     return None
-
-    # def construct_dynamic_prompt(self):
-    #     """Construct the dynamic prompt"""
-    #     tools_description = self.get_tool_description()
-    #     return DYNAMICAL_TOOL_USAGE.format(tools=tools_description)
-
-    # def extract_tool_commands(self, text: str):
-    #     """
-    #     Extract the tool commands from the text
-
-    #     Example:
-    #     ```json
-    #     {
-    #         "tool": "tool_name",
-    #         "params": {
-    #             "tool1": "inputs",
-    #             "param2": "value2"
-    #         }
-    #     }
-    #     ```
-
-    #     """
-    #     # Regex to find JSON like strings
-    #     pattern = r"```json(.+?)```"
-    #     matches = re.findall(pattern, text, re.DOTALL)
-    #     json_commands = []
-    #     for match in matches:
-    #         try:
-    #             json_commands = json.loads(match)
-    #             json_commands.append(json_commands)
-    #         except Exception as error:
-    #             print(f"Error parsing JSON command: {error}")
-
-    # def parse_and_execute_tools(self, response):
-    #     """Parse and execute the tools"""
-    #     json_commands = self.extract_tool_commands(response)
-    #     for command in json_commands:
-    #         tool_name = command.get("tool")
-    #         params = command.get("parmas", {})
-    #         self.execute_tool(tool_name, params)
-
-    # def execute_tools(self, tool_name, params):
-    #     """Execute the tool with the provided params"""
-    #     tool = self.tool_find_by_name(tool_name)
-    #     if tool:
-    #         # Execute the tool with the provided parameters
-    #         tool_result = tool.run(**params)
-    #         print(tool_result)
-
-    def truncate_history(self):
-        """
-        Take the history and truncate it to fit into the model context length
-        """
-        truncated_history = self.memory[-1][-self.context_length :]
-        self.memory[-1] = truncated_history
-
-    def add_task_to_memory(self, task: str):
-        """Add the task to the memory"""
-        self.memory.append([f"{self.user_name}: {task}"])
-
-    def add_message_to_memory(self, message: str):
-        """Add the message to the memory"""
-        self.memory[-1].append(message)
-
-    def add_message_to_memory_and_truncate(self, message: str):
-        """Add the message to the memory and truncate"""
-        self.memory[-1].append(message)
-        self.truncate_history()
-
-    def print_dashboard(self, task: str):
-        """Print dashboard"""
-        model_config = self.get_llm_init_params()
-        print(colored("Initializing Agent Dashboard...", "yellow"))
-
-        print(
-            colored(
-                f"""
-                Flow Dashboard
-                --------------------------------------------
-
-                Flow loop is initializing for {self.max_loops} with the following configuration:
-                ----------------------------------------
-
-                Flow Configuration:
-                    Name: {self.agent_name}
-                    Description: {self.agent_description}
-                    Standard Operating Procedure: {self.sop}
-                    System Prompt: {self.system_prompt} 
-                    Task: {task}
-                    Max Loops: {self.max_loops}
-                    Stopping Condition: {self.stopping_condition}
-                    Loop Interval: {self.loop_interval}
-                    Retry Attempts: {self.retry_attempts}
-                    Retry Interval: {self.retry_interval}
-                    Interactive: {self.interactive}
-                    Dashboard: {self.dashboard}
-                    Dynamic Temperature: {self.dynamic_temperature}
-                    Autosave: {self.autosave}
-                    Saved State: {self.saved_state_path}
-                    Model Configuration: {model_config}
-
-                ----------------------------------------
-                """,
-                "green",
-            )
-        )
-
-        # print(dashboard)
-
-    def activate_autonomous_agent(self):
-        """Print the autonomous agent activation message"""
-        try:
-            print(colored("Initializing Autonomous Agent...", "yellow"))
-            # print(colored("Loading modules...", "yellow"))
-            # print(colored("Modules loaded successfully.", "green"))
-            print(colored("Autonomous Agent Activated.", "cyan", attrs=["bold"]))
-            print(colored("All systems operational. Executing task...", "green"))
-        except Exception as error:
-            print(
-                colored(
-                    (
-                        "Error activating autonomous agent. Try optimizing your"
-                        " parameters..."
-                    ),
-                    "red",
-                )
-            )
-            print(error)
-
-    def run(self, task: str, **kwargs):
-        """
-        Run the autonomous agent loop
-
-        Args:
-            task (str): The initial task to run
-
-        Flow:
-        1. Generate a response
-        2. Check stopping condition
-        3. If stopping condition is met, stop
-        4. If stopping condition is not met, generate a response
-        5. Repeat until stopping condition is met or max_loops is reached
-
-        """
-        try:
-            # dynamic_prompt = self.construct_dynamic_prompt()
-            # combined_prompt = f"{dynamic_prompt}\n{task}"
-
-            # Activate Autonomous agent message
-            self.activate_autonomous_agent()
-
-            response = task  # or combined_prompt
-            history = [f"{self.user_name}: {task}"]
-
-            # If dashboard = True then print the dashboard
-            if self.dashboard:
-                self.print_dashboard(task)
-
-            loop_count = 0
-            # for i in range(self.max_loops):
-            while self.max_loops == "auto" or loop_count < self.max_loops:
-                loop_count += 1
-                print(colored(f"\nLoop {loop_count} of {self.max_loops}", "blue"))
-                print("\n")
-
-                if self.stopping_token:
-                    if self._check_stopping_condition(response) or parse_done_token(
-                        response
-                    ):
-                        break
-
-                # Adjust temperature, comment if no work
-                if self.dynamic_temperature:
-                    self.dynamic_temperature()
-
-                # Preparing the prompt
-                task = self.agent_history_prompt(FLOW_SYSTEM_PROMPT, response)
-
-                attempt = 0
-                while attempt < self.retry_attempts:
-                    try:
-                        response = self.llm(
-                            task,
-                            **kwargs,
-                        )
-
-                        if self.code_interpreter:
-                            self.run_code(response)
-                        # If there are any tools then parse and execute them
-                        # if self.tools:
-                        #     self.parse_and_execute_tools(response)
-
-                        if self.interactive:
-                            print(f"AI: {response}")
-                            history.append(f"AI: {response}")
-                            response = input("You: ")
-                            history.append(f"Human: {response}")
-                        else:
-                            print(f"AI: {response}")
-                            history.append(f"AI: {response}")
-                            # print(response)
-                        break
-                    except Exception as e:
-                        logging.error(f"Error generating response: {e}")
-                        attempt += 1
-                        time.sleep(self.retry_interval)
-                history.append(response)
-                time.sleep(self.loop_interval)
-            self.memory.append(history)
-
-            if self.autosave:
-                save_path = self.saved_state_path or "flow_state.json"
-                print(colored(f"Autosaving flow state to {save_path}", "green"))
-                self.save_state(save_path)
-
-            if self.return_history:
-                return response, history
-
-            return response
-        except Exception as error:
-            print(f"Error running flow: {error}")
-            raise
-
-    def __call__(self, task: str, **kwargs):
-        """
-        Run the autonomous agent loop
-
-        Args:
-            task (str): The initial task to run
-
-        Flow:
-        1. Generate a response
-        2. Check stopping condition
-        3. If stopping condition is met, stop
-        4. If stopping condition is not met, generate a response
-        5. Repeat until stopping condition is met or max_loops is reached
-
-        """
-        try:
-            # dynamic_prompt = self.construct_dynamic_prompt()
-            # combined_prompt = f"{dynamic_prompt}\n{task}"
-
-            # Activate Autonomous agent message
-            self.activate_autonomous_agent()
-
-            response = task  # or combined_prompt
-            history = [f"{self.user_name}: {task}"]
-
-            # If dashboard = True then print the dashboard
-            if self.dashboard:
-                self.print_dashboard(task)
-
-            loop_count = 0
-            # for i in range(self.max_loops):
-            while self.max_loops == "auto" or loop_count < self.max_loops:
-                loop_count += 1
-                print(colored(f"\nLoop {loop_count} of {self.max_loops}", "blue"))
-                print("\n")
-
-                if self.stopping_token:
-                    if self._check_stopping_condition(response) or parse_done_token(
-                        response
-                    ):
-                        break
-
-                # Adjust temperature, comment if no work
-                if self.dynamic_temperature:
-                    self.dynamic_temperature()
-
-                # Preparing the prompt
-                task = self.agent_history_prompt(FLOW_SYSTEM_PROMPT, response)
-
-                attempt = 0
-                while attempt < self.retry_attempts:
-                    try:
-                        response = self.llm(
-                            task,
-                            **kwargs,
-                        )
-
-                        if self.code_interpreter:
-                            self.run_code(response)
-                        # If there are any tools then parse and execute them
-                        # if self.tools:
-                        #     self.parse_and_execute_tools(response)
-
-                        if self.interactive:
-                            print(f"AI: {response}")
-                            history.append(f"AI: {response}")
-                            response = input("You: ")
-                            history.append(f"Human: {response}")
-                        else:
-                            print(f"AI: {response}")
-                            history.append(f"AI: {response}")
-                            # print(response)
-                        break
-                    except Exception as e:
-                        logging.error(f"Error generating response: {e}")
-                        attempt += 1
-                        time.sleep(self.retry_interval)
-                history.append(response)
-                time.sleep(self.loop_interval)
-            self.memory.append(history)
-
-            if self.autosave:
-                save_path = self.saved_state_path or "flow_state.json"
-                print(colored(f"Autosaving flow state to {save_path}", "green"))
-                self.save_state(save_path)
-
-            if self.return_history:
-                return response, history
-
-            return response
-        except Exception as error:
-            print(f"Error running flow: {error}")
-            raise
-
-    async def arun(self, task: str, **kwargs):
-        """
-        Run the autonomous agent loop aschnronously
-
-        Args:
-            task (str): The initial task to run
-
-        Flow:
-        1. Generate a response
-        2. Check stopping condition
-        3. If stopping condition is met, stop
-        4. If stopping condition is not met, generate a response
-        5. Repeat until stopping condition is met or max_loops is reached
-
-        """
-        # Activate Autonomous agent message
-        self.activate_autonomous_agent()
-
-        response = task
-        history = [f"{self.user_name}: {task}"]
-
-        # If dashboard = True then print the dashboard
-        if self.dashboard:
-            self.print_dashboard(task)
-
-        loop_count = 0
-        # for i in range(self.max_loops):
-        while self.max_loops == "auto" or loop_count < self.max_loops:
-            loop_count += 1
-            print(colored(f"\nLoop {loop_count} of {self.max_loops}", "blue"))
-            print("\n")
-
-            if self._check_stopping_condition(response) or parse_done_token(response):
-                break
-
-            # Adjust temperature, comment if no work
-            if self.dynamic_temperature:
-                self.dynamic_temperature()
-
-            # Preparing the prompt
-            task = self.agent_history_prompt(FLOW_SYSTEM_PROMPT, response)
-
-            attempt = 0
-            while attempt < self.retry_attempts:
-                try:
-                    response = self.llm(
-                        task**kwargs,
-                    )
-                    if self.interactive:
-                        print(f"AI: {response}")
-                        history.append(f"AI: {response}")
-                        response = input("You: ")
-                        history.append(f"Human: {response}")
-                    else:
-                        print(f"AI: {response}")
-                        history.append(f"AI: {response}")
-                        print(response)
-                    break
-                except Exception as e:
-                    logging.error(f"Error generating response: {e}")
-                    attempt += 1
-                    time.sleep(self.retry_interval)
-            history.append(response)
-            time.sleep(self.loop_interval)
-        self.memory.append(history)
-
-        if self.autosave:
-            save_path = self.saved_state_path or "flow_state.json"
-            print(colored(f"Autosaving flow state to {save_path}", "green"))
-            self.save_state(save_path)
-
-        if self.return_history:
-            return response, history
-
-        return response
-
-    def _run(self, **kwargs: Any) -> str:
-        """Generate a result using the provided keyword args."""
-        task = self.format_prompt(**kwargs)
-        response, history = self._generate(task, task)
-        logging.info(f"Message history: {history}")
-        return response
-
-    def agent_history_prompt(
-        self,
-        system_prompt: str = FLOW_SYSTEM_PROMPT,
-        history=None,
-    ):
-        """
-        Generate the agent history prompt
-
-        Args:
-            system_prompt (str): The system prompt
-            history (List[str]): The history of the conversation
-
-        Returns:
-            str: The agent history prompt
-        """
-        if self.sop:
-            system_prompt = system_prompt or self.system_prompt
-            agent_history_prompt = f"""
-                SYSTEM_PROMPT: {system_prompt}
-
-                Follow this standard operating procedure (SOP) to complete tasks:
-                {self.sop}
-                
-                -----------------
-                History of conversations between yourself and your user {self.user_name}: {history}
-            """
-            return agent_history_prompt
-        else:
-            system_prompt = system_prompt or self.system_prompt
-            agent_history_prompt = f"""
-                SYSTEM_PROMPT: {system_prompt}
-
-
-                History: {history}
-            """
-            return agent_history_prompt
-
-    async def run_concurrent(self, tasks: List[str], **kwargs):
-        """
-        Run a batch of tasks concurrently and handle an infinite level of task inputs.
-
-        Args:
-            tasks (List[str]): A list of tasks to run.
-        """
-        task_coroutines = [self.run_async(task, **kwargs) for task in tasks]
-        completed_tasks = await asyncio.gather(*task_coroutines)
-        return completed_tasks
-
-    def bulk_run(self, inputs: List[Dict[str, Any]]) -> List[str]:
-        """Generate responses for multiple input sets."""
-        return [self.run(**input_data) for input_data in inputs]
-
-    @staticmethod
-    def from_llm_and_template(llm: Any, template: str) -> "Flow":
-        """Create FlowStream from LLM and a string template."""
-        return Flow(llm=llm, template=template)
-
-    @staticmethod
-    def from_llm_and_template_file(llm: Any, template_file: str) -> "Flow":
-        """Create FlowStream from LLM and a template file."""
-        with open(template_file, "r") as f:
-            template = f.read()
-        return Flow(llm=llm, template=template)
-
-    def save(self, file_path) -> None:
-        with open(file_path, "w") as f:
-            json.dump(self.memory, f)
-        print(f"Saved flow history to {file_path}")
-
-    def load(self, file_path: str):
-        """
-        Load the flow history from a file.
-
-        Args:
-            file_path (str): The path to the file containing the saved flow history.
-        """
-        with open(file_path, "r") as f:
-            self.memory = json.load(f)
-        print(f"Loaded flow history from {file_path}")
-
-    def validate_response(self, response: str) -> bool:
-        """Validate the response based on certain criteria"""
-        if len(response) < 5:
-            print("Response is too short")
-            return False
-        return True
-
-    def print_history_and_memory(self):
-        """
-        Prints the entire history and memory of the flow.
-        Each message is colored and formatted for better readability.
-        """
-        print(colored("Flow History and Memory", "cyan", attrs=["bold"]))
-        print(colored("========================", "cyan", attrs=["bold"]))
-        for loop_index, history in enumerate(self.memory, start=1):
-            print(colored(f"\nLoop {loop_index}:", "yellow", attrs=["bold"]))
-            for message in history:
-                speaker, _, message_text = message.partition(": ")
-                if "Human" in speaker:
-                    print(colored(f"{speaker}:", "green") + f" {message_text}")
-                else:
-                    print(colored(f"{speaker}:", "blue") + f" {message_text}")
-            print(colored("------------------------", "cyan"))
-        print(colored("End of Flow History", "cyan", attrs=["bold"]))
-
-    def step(self, task: str, **kwargs):
-        """
-
-        Executes a single step in the flow interaction, generating a response
-        from the language model based on the given input text.
-
-        Args:
-            input_text (str): The input text to prompt the language model with.
-
-        Returns:
-            str: The language model's generated response.
-
-        Raises:
-            Exception: If an error occurs during response generation.
-
-        """
-        try:
-            # Generate the response using lm
-            response = self.llm(task, **kwargs)
-
-            # Update the flow's history with the new interaction
-            if self.interactive:
-                self.memory.append(f"AI: {response}")
-                self.memory.append(f"Human: {task}")
-            else:
-                self.memory.append(f"AI: {response}")
-
-            return response
-        except Exception as error:
-            logging.error(f"Error generating response: {error}")
-            raise
-
-    def graceful_shutdown(self):
-        """Gracefully shutdown the system saving the state"""
-        print(colored("Shutting down the system...", "red"))
-        return self.save_state("flow_state.json")
-
-    def run_with_timeout(self, task: str, timeout: int = 60) -> str:
-        """Run the loop but stop if it takes longer than the timeout"""
-        start_time = time.time()
-        response = self.run(task)
-        end_time = time.time()
-        if end_time - start_time > timeout:
-            print("Operaiton timed out")
-            return "Timeout"
-        return response
-
-    def analyze_feedback(self):
-        """Analyze the feedback for issues"""
-        feedback_counts = {}
-        for feedback in self.feedback:
-            if feedback in feedback_counts:
-                feedback_counts[feedback] += 1
-            else:
-                feedback_counts[feedback] = 1
-        print(f"Feedback counts: {feedback_counts}")
-
-    def undo_last(self) -> Tuple[str, str]:
-        """
-        Response the last response and return the previous state
-
-        Example:
-        # Feature 2: Undo functionality
-        response = flow.run("Another task")
-        print(f"Response: {response}")
-        previous_state, message = flow.undo_last()
-        print(message)
-
-        """
-        if len(self.memory) < 2:
-            return None, None
-
-        # Remove the last response
-        self.memory.pop()
-
-        # Get the previous state
-        previous_state = self.memory[-1][-1]
-        return previous_state, f"Restored to {previous_state}"
-
-    # Response Filtering
-    def add_response_filter(self, filter_word: str) -> None:
-        """
-        Add a response filter to filter out certain words from the response
-
-        Example:
-        flow.add_response_filter("Trump")
-        flow.run("Generate a report on Trump")
-
-
-        """
-        self.reponse_filters.append(filter_word)
-
-    def apply_reponse_filters(self, response: str) -> str:
-        """
-        Apply the response filters to the response
-
-
-        """
-        for word in self.response_filters:
-            response = response.replace(word, "[FILTERED]")
-        return response
-
-    def filtered_run(self, task: str) -> str:
-        """
-        # Feature 3: Response filtering
-        flow.add_response_filter("report")
-        response = flow.filtered_run("Generate a report on finance")
-        print(response)
-        """
-        raw_response = self.run(task)
-        return self.apply_response_filters(raw_response)
-
-    def interactive_run(self, max_loops: int = 5) -> None:
-        """Interactive run mode"""
-        response = input("Start the cnversation")
-
-        for i in range(max_loops):
-            ai_response = self.streamed_generation(response)
-            print(f"AI: {ai_response}")
-
-            # Get user input
-            response = input("You: ")
-
-    def streamed_generation(self, prompt: str) -> str:
-        """
-        Stream the generation of the response
-
-        Args:
-            prompt (str): The prompt to use
-
-        Example:
-        # Feature 4: Streamed generation
-        response = flow.streamed_generation("Generate a report on finance")
-        print(response)
-
-        """
-        tokens = list(prompt)
-        response = ""
-        for token in tokens:
-            time.sleep(0.1)
-            response += token
-            print(token, end="", flush=True)
-        print()
-        return response
-
-    def get_llm_params(self):
-        """
-        Extracts and returns the parameters of the llm object for serialization.
-        It assumes that the llm object has an __init__ method
-        with parameters that can be used to recreate it.
-        """
-        if not hasattr(self.llm, "__init__"):
-            return None
-
-        init_signature = inspect.signature(self.llm.__init__)
-        params = init_signature.parameters
-        llm_params = {}
-
-        for name, param in params.items():
-            if name == "self":
-                continue
-            if hasattr(self.llm, name):
-                value = getattr(self.llm, name)
-                if isinstance(
-                    value, (str, int, float, bool, list, dict, tuple, type(None))
-                ):
-                    llm_params[name] = value
-                else:
-                    llm_params[name] = str(
-                        value
-                    )  # For non-serializable objects, save their string representation.
-
-        return llm_params
-
-    def save_state(self, file_path: str) -> None:
-        """
-        Saves the current state of the flow to a JSON file, including the llm parameters.
-
-        Args:
-            file_path (str): The path to the JSON file where the state will be saved.
-
-        Example:
-        >>> flow.save_state('saved_flow.json')
-        """
-        state = {
-            "memory": self.memory,
-            # "llm_params": self.get_llm_params(),
-            "loop_interval": self.loop_interval,
-            "retry_attempts": self.retry_attempts,
-            "retry_interval": self.retry_interval,
-            "interactive": self.interactive,
-            "dashboard": self.dashboard,
-            "dynamic_temperature": self.dynamic_temperature,
-        }
-
-        with open(file_path, "w") as f:
-            json.dump(state, f, indent=4)
-
-        saved = colored("Saved flow state to", "green")
-        print(f"{saved} {file_path}")
-
-    def load_state(self, file_path: str):
-        """
-        Loads the state of the flow from a json file and restores the configuration and memory.
-
-
-        Example:
-        >>> flow = Flow(llm=llm_instance, max_loops=5)
-        >>> flow.load_state('saved_flow.json')
-        >>> flow.run("Continue with the task")
-
-        """
-        with open(file_path, "r") as f:
-            state = json.load(f)
-
-        # Restore other saved attributes
-        self.memory = state.get("memory", [])
-        self.max_loops = state.get("max_loops", 5)
-        self.loop_interval = state.get("loop_interval", 1)
-        self.retry_attempts = state.get("retry_attempts", 3)
-        self.retry_interval = state.get("retry_interval", 1)
-        self.interactive = state.get("interactive", False)
-
-        print(f"Flow state loaded from {file_path}")
-
-    def retry_on_failure(self, function, retries: int = 3, retry_delay: int = 1):
-        """Retry wrapper for LLM calls."""
-        attempt = 0
-        while attempt < retries:
-            try:
-                return function()
-            except Exception as error:
-                logging.error(f"Error generating response: {error}")
-                attempt += 1
-                time.sleep(retry_delay)
-        raise Exception("All retry attempts failed")
-
-    def generate_reply(self, history: str, **kwargs) -> str:
-        """
-        Generate a response based on initial or task
-        """
-        prompt = f"""
-
-        SYSTEM_PROMPT: {self.system_prompt}
-
-        History: {history}
-
-        Your response:
-        """
-        response = self.llm(prompt, **kwargs)
-        return {"role": self.agent_name, "content": response}
-
-    def update_system_prompt(self, system_prompt: str):
-        """Upddate the system message"""
-        self.system_prompt = system_prompt
-
-    def update_max_loops(self, max_loops: int):
-        """Update the max loops"""
-        self.max_loops = max_loops
-
-    def update_loop_interval(self, loop_interval: int):
-        """Update the loop interval"""
-        self.loop_interval = loop_interval
-
-    def update_retry_attempts(self, retry_attempts: int):
-        """Update the retry attempts"""
-        self.retry_attempts = retry_attempts
-
-    def update_retry_interval(self, retry_interval: int):
-        """Update the retry interval"""
-        self.retry_interval = retry_interval
-
-    def reset(self):
-        """Reset the flow"""
-        self.memory = []
-
-    def run_code(self, code: str):
-        """
-        text -> parse_code by looking for code inside 6 backticks `````-> run_code
-        """
-        parsed_code = extract_code_in_backticks_in_string(code)
-        run_code = self.code_executor.run(parsed_code)
-        return run_code
-
-    def tool_prompt_prep(self, api_docs: str = None, required_api: str = None):
-        """
-        Prepare the tool prompt
-        """
-        PROMPT = f"""
-        # Task
-        You will be provided with a list of APIs. These APIs will have a
-        description and a list of parameters and return types for each tool. Your
-        task involves creating 3 varied, complex, and detailed user scenarios
-        that require at least 5 API calls to complete involving at least 3
-        different APIs. One of these APIs will be explicitly provided and the
-        other two will be chosen by you.
-
-        For instance, given the APIs: SearchHotels, BookHotel, CancelBooking,
-        GetNFLNews. Given that GetNFLNews is explicitly provided, your scenario
-        should articulate something akin to:
-
-        "The user wants to see if the Broncos won their last game (GetNFLNews).
-        They then want to see if that qualifies them for the playoffs and who
-        they will be playing against (GetNFLNews). The Broncos did make it into
-        the playoffs, so the user wants watch the game in person. They want to
-        look for hotels where the playoffs are occurring (GetNBANews +
-        SearchHotels). After looking at the options, the user chooses to book a
-        3-day stay at the cheapest 4-star option (BookHotel)."
-        13
-
-        This scenario exemplifies a scenario using 5 API calls. The scenario is
-        complex, detailed, and concise as desired. The scenario also includes two
-        APIs used in tandem, the required API, GetNBANews to search for the
-        playoffs location and SearchHotels to find hotels based on the returned
-        location. Usage of multiple APIs in tandem is highly desirable and will
-        receive a higher score. Ideally each scenario should contain one or more
-        instances of multiple APIs being used in tandem.
-
-        Note that this scenario does not use all the APIs given and re-uses the "
-        GetNBANews" API. Re-using APIs is allowed, but each scenario should
-        involve at least 3 different APIs. Note that API usage is also included
-        in the scenario, but exact parameters are not necessary. You must use a
-        different combination of APIs for each scenario. All APIs must be used in
-        at least one scenario. You can only use the APIs provided in the APIs
-        section.
-        
-        Note that API calls are not explicitly mentioned and their uses are
-        included in parentheses. This behaviour should be mimicked in your
-        response.
-        Deliver your response in this format:
-        β€˜β€˜β€˜
-        - Scenario 1: <Scenario1>
-        - Scenario 2: <Scenario2>
-        - Scenario 3: <Scenario3>
-        β€˜β€˜β€˜
-        # APIs
-        β€˜β€˜β€˜
-        {api_docs}
-        β€˜β€˜β€˜
-        # Response
-        Required API: {required_api}
-        Scenarios with >=5 API calls:
-        β€˜β€˜β€˜
-        - Scenario 1: <Scenario1>
-        """
-
-    def self_healing(self, **kwargs):
-        """
-        Self healing by debugging errors and refactoring its own code
-
-        Args:
-            **kwargs (Any): Any additional keyword arguments
-        """
-        pass
-
-    # def refactor_code(
-    #     self,
-    #     file: str,
-    #     changes: List,
-    #     confirm: bool = False
-    # ):
-    #     """
-    #     Refactor the code
-    #     """
-    #     with open(file) as f:
-    #         original_file_lines = f.readlines()
-
-    #     # Filter out the changes that are not confirmed
-    #     operation_changes = [
-    #         change for change in changes if "operation" in change
-    #     ]
-    #     explanations = [
-    #         change["explanation"] for change in changes if "explanation" in change
-    #     ]
-
-    #     # Sort the changes in reverse line order
-    #     # explanations.sort(key=lambda x: x["line", reverse=True])
-
-    # # def error_prompt_inject(
-    # #     self,
-    # #     file_path: str,
-    # #     args: List,
-    # #     error: str,
-    # # ):
-    # #     with open(file_path, "r") as f:
-    # #         file_lines = f.readlines()
-
-    # #     file_with_lines = []
-    # #     for i, line in enumerate(file_lines):
-    # #         file_with_lines.append(str(i + 1) + "" + line)
-    # #     file_with_lines = "".join(file_with_lines)
-
-    # #     prompt = f"""
-    # #         Here is the script that needs fixing:\n\n
-    # #         {file_with_lines}\n\n
-    # #         Here are the arguments it was provided:\n\n
-    # #         {args}\n\n
-    # #         Here is the error message:\n\n
-    # #         {error}\n
-    # #         "Please provide your suggested changes, and remember to stick to the "
-    # #         exact format as described above.
-    # #         """
-
-    # #     # Print(prompt)
diff --git a/swarms/structs/sequential_workflow.py b/swarms/structs/sequential_workflow.py
index d1c600f0..93165aee 100644
--- a/swarms/structs/sequential_workflow.py
+++ b/swarms/structs/sequential_workflow.py
@@ -1,25 +1,11 @@
-"""
-TODO:
-- Add a method to update the arguments of a task
-- Add a method to get the results of each task
-- Add a method to get the results of a specific task
-- Add a method to get the results of the workflow
-- Add a method to get the results of the workflow as a dataframe
-
-
-- Add a method to run the workflow in parallel with a pool of workers and a queue and a dashboard
-- Add a dashboard to visualize the workflow
-- Add async support
-- Add context manager support
-- Add workflow history
-"""
+import concurrent.futures
 import json
 from dataclasses import dataclass, field
 from typing import Any, Callable, Dict, List, Optional, Union
 
 from termcolor import colored
 
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 
 
 # Define a generic Task that can handle different types of callable objects
@@ -29,48 +15,63 @@ class Task:
     Task class for running a task in a sequential workflow.
 
 
+    Args:
+        description (str): The description of the task.
+        agent (Union[Callable, Agent]): The model or agent to execute the task.
+        args (List[Any]): Additional arguments to pass to the task execution.
+        kwargs (Dict[str, Any]): Additional keyword arguments to pass to the task execution.
+        result (Any): The result of the task execution.
+        history (List[Any]): The history of the task execution.
+
+    Methods:
+        execute: Execute the task.
+
+
     Examples:
-    >>> from swarms.structs import Task, Flow
+    >>> from swarms.structs import Task, Agent
     >>> from swarms.models import OpenAIChat
-    >>> flow = Flow(llm=OpenAIChat(openai_api_key=""), max_loops=1, dashboard=False)
-    >>> task = Task(description="What's the weather in miami", flow=flow)
+    >>> agent = Agent(llm=OpenAIChat(openai_api_key=""), max_loops=1, dashboard=False)
+    >>> task = Task(description="What's the weather in miami", agent=agent)
     >>> task.execute()
     >>> task.result
 
-
-
     """
 
     description: str
-    flow: Union[Callable, Flow]
+    agent: Union[Callable, Agent]
     args: List[Any] = field(default_factory=list)
     kwargs: Dict[str, Any] = field(default_factory=dict)
     result: Any = None
     history: List[Any] = field(default_factory=list)
+    # logger = logging.getLogger(__name__)
 
     def execute(self):
         """
         Execute the task.
 
         Raises:
-            ValueError: If a Flow instance is used as a task and the 'task' argument is not provided.
-
-
-
+            ValueError: If a Agent instance is used as a task and the 'task' argument is not provided.
         """
-        if isinstance(self.flow, Flow):
-            # Add a prompt to notify the Flow of the sequential workflow
+        if isinstance(self.agent, Agent):
+            # Add a prompt to notify the Agent of the sequential workflow
             if "prompt" in self.kwargs:
                 self.kwargs["prompt"] += (
-                    f"\n\nPrevious output: {self.result}" if self.result else ""
+                    f"\n\nPrevious output: {self.result}"
+                    if self.result
+                    else ""
                 )
             else:
-                self.kwargs["prompt"] = f"Main task: {self.description}" + (
-                    f"\n\nPrevious output: {self.result}" if self.result else ""
+                self.kwargs["prompt"] = (
+                    f"Main task: {self.description}"
+                    + (
+                        f"\n\nPrevious output: {self.result}"
+                        if self.result
+                        else ""
+                    )
                 )
-            self.result = self.flow.run(*self.args, **self.kwargs)
+            self.result = self.agent.run(*self.args, **self.kwargs)
         else:
-            self.result = self.flow(*self.args, **self.kwargs)
+            self.result = self.agent(*self.args, **self.kwargs)
 
         self.history.append(self.result)
 
@@ -104,38 +105,66 @@ class SequentialWorkflow:
 
     """
 
+    name: str = None
+    description: str = None
     tasks: List[Task] = field(default_factory=list)
     max_loops: int = 1
     autosave: bool = False
-    name: str = (None,)
-    description: str = (None,)
-    saved_state_filepath: Optional[str] = "sequential_workflow_state.json"
+    saved_state_filepath: Optional[str] = (
+        "sequential_workflow_state.json"
+    )
     restore_state_filepath: Optional[str] = None
     dashboard: bool = False
 
-    def add(self, task: str, flow: Union[Callable, Flow], *args, **kwargs) -> None:
+    def add(
+        self,
+        agent: Union[Callable, Agent],
+        task: Optional[str] = None,
+        *args,
+        **kwargs,
+    ) -> None:
         """
         Add a task to the workflow.
 
         Args:
-            task (str): The task description or the initial input for the Flow.
-            flow (Union[Callable, Flow]): The model or flow to execute the task.
+            agent (Union[Callable, Agent]): The model or agent to execute the task.
+            task (str): The task description or the initial input for the Agent.
+
             *args: Additional arguments to pass to the task execution.
             **kwargs: Additional keyword arguments to pass to the task execution.
         """
-        # If the flow is a Flow instance, we include the task in kwargs for Flow.run()
-        if isinstance(flow, Flow):
-            kwargs["task"] = task  # Set the task as a keyword argument for Flow
+        try:
+            # If the agent is a Agent instance, we include the task in kwargs for Agent.run()
+            if isinstance(agent, Agent):
+                kwargs["task"] = (
+                    task  # Set the task as a keyword argument for Agent
+                )
 
-        # Append the task to the tasks list
-        self.tasks.append(
-            Task(description=task, flow=flow, args=list(args), kwargs=kwargs)
-        )
+            # Append the task to the tasks list
+            self.tasks.append(
+                Task(
+                    description=task,
+                    agent=agent,
+                    args=list(args),
+                    kwargs=kwargs,
+                )
+            )
+        except Exception as error:
+            print(
+                colored(
+                    f"Error adding task to workflow: {error}", "red"
+                ),
+            )
 
     def reset_workflow(self) -> None:
         """Resets the workflow by clearing the results of each task."""
-        for task in self.tasks:
-            task.result = None
+        try:
+            for task in self.tasks:
+                task.result = None
+        except Exception as error:
+            print(
+                colored(f"Error resetting workflow: {error}", "red"),
+            )
 
     def get_task_results(self) -> Dict[str, Any]:
         """
@@ -144,19 +173,39 @@ class SequentialWorkflow:
         Returns:
             Dict[str, Any]: The results of each task in the workflow
         """
-        return {task.description: task.result for task in self.tasks}
+        try:
+            return {
+                task.description: task.result for task in self.tasks
+            }
+        except Exception as error:
+            print(
+                colored(
+                    f"Error getting task results: {error}", "red"
+                ),
+            )
 
-    def remove_task(self, task_description: str) -> None:
-        self.tasks = [
-            task for task in self.tasks if task.description != task_description
-        ]
+    def remove_task(self, task: str) -> None:
+        """Remove tasks from sequential workflow"""
+        try:
+            self.tasks = [
+                task
+                for task in self.tasks
+                if task.description != task
+            ]
+        except Exception as error:
+            print(
+                colored(
+                    f"Error removing task from workflow: {error}",
+                    "red",
+                ),
+            )
 
-    def update_task(self, task_description: str, **updates) -> None:
+    def update_task(self, task: str, **updates) -> None:
         """
         Updates the arguments of a task in the workflow.
 
         Args:
-            task_description (str): The description of the task to update.
+            task (str): The description of the task to update.
             **updates: The updates to apply to the task.
 
         Raises:
@@ -174,15 +223,100 @@ class SequentialWorkflow:
         {'max_tokens': 1000}
 
         """
-        for task in self.tasks:
-            if task.description == task_description:
-                task.kwargs.update(updates)
-                break
-        else:
-            raise ValueError(f"Task {task_description} not found in workflow.")
+        try:
+            for task in self.tasks:
+                if task.description == task:
+                    task.kwargs.update(updates)
+                    break
+            else:
+                raise ValueError(
+                    f"Task {task} not found in workflow."
+                )
+        except Exception as error:
+            print(
+                colored(
+                    f"Error updating task in workflow: {error}", "red"
+                ),
+            )
+
+    def delete_task(self, task: str) -> None:
+        """
+        Delete a task from the workflow.
+
+        Args:
+            task (str): The description of the task to delete.
+
+        Raises:
+            ValueError: If the task is not found in the workflow.
+
+        Examples:
+        >>> from swarms.models import OpenAIChat
+        >>> from swarms.structs import SequentialWorkflow
+        >>> llm = OpenAIChat(openai_api_key="")
+        >>> workflow = SequentialWorkflow(max_loops=1)
+        >>> workflow.add("What's the weather in miami", llm)
+        >>> workflow.add("Create a report on these metrics", llm)
+        >>> workflow.delete_task("What's the weather in miami")
+        >>> workflow.tasks
+        [Task(description='Create a report on these metrics', agent=Agent(llm=OpenAIChat(openai_api_key=''), max_loops=1, dashboard=False), args=[], kwargs={}, result=None, history=[])]
+        """
+        try:
+            for task in self.tasks:
+                if task.description == task:
+                    self.tasks.remove(task)
+                    break
+            else:
+                raise ValueError(
+                    f"Task {task} not found in workflow."
+                )
+        except Exception as error:
+            print(
+                colored(
+                    f"Error deleting task from workflow: {error}",
+                    "red",
+                ),
+            )
+
+    def concurrent_run(self):
+        """
+        Concurrently run the workflow using a pool of workers.
+
+        Examples:
+        >>> from swarms.models import OpenAIChat
+        >>> from swarms.structs import SequentialWorkflow
+        >>> llm = OpenAIChat(openai_api_key="")
+        >>> workflow = SequentialWorkflow(max_loops=1)
+
+        """
+        try:
+            with concurrent.futures.ThreadPoolExecutor() as executor:
+                futures_to_task = {
+                    executor.submit(task.run): task
+                    for task in self.tasks
+                }
+                results = []
+                for future in concurrent.futures.as_completed(
+                    futures_to_task
+                ):
+                    task = futures_to_task[future]
+
+                    try:
+                        result = future.result()
+                    except Exception as error:
+                        print(f"Error running workflow: {error}")
+                    else:
+                        results.append(result)
+                        print(
+                            f"Task {task} completed successfully with"
+                            f" result: {result}"
+                        )
+        except Exception as error:
+            print(colored(f"Error running workflow: {error}", "red"))
 
     def save_workflow_state(
-        self, filepath: Optional[str] = "sequential_workflow_state.json", **kwargs
+        self,
+        filepath: Optional[str] = "sequential_workflow_state.json",
+        **kwargs,
     ) -> None:
         """
         Saves the workflow state to a json file.
@@ -199,26 +333,35 @@ class SequentialWorkflow:
         >>> workflow.add("Create a report on these metrics", llm)
         >>> workflow.save_workflow_state("sequential_workflow_state.json")
         """
-        filepath = filepath or self.saved_state_filepath
-
-        with open(filepath, "w") as f:
-            # Saving the state as a json for simplicuty
-            state = {
-                "tasks": [
-                    {
-                        "description": task.description,
-                        "args": task.args,
-                        "kwargs": task.kwargs,
-                        "result": task.result,
-                        "history": task.history,
-                    }
-                    for task in self.tasks
-                ],
-                "max_loops": self.max_loops,
-            }
-            json.dump(state, f, indent=4)
+        try:
+            filepath = filepath or self.saved_state_filepath
+
+            with open(filepath, "w") as f:
+                # Saving the state as a json for simplicuty
+                state = {
+                    "tasks": [
+                        {
+                            "description": task.description,
+                            "args": task.args,
+                            "kwargs": task.kwargs,
+                            "result": task.result,
+                            "history": task.history,
+                        }
+                        for task in self.tasks
+                    ],
+                    "max_loops": self.max_loops,
+                }
+                json.dump(state, f, indent=4)
+        except Exception as error:
+            print(
+                colored(
+                    f"Error saving workflow state: {error}",
+                    "red",
+                )
+            )
 
     def workflow_bootup(self, **kwargs) -> None:
+        """Boots up the workflow."""
         print(
             colored(
                 """
@@ -260,10 +403,6 @@ class SequentialWorkflow:
                 --------------------------------
                 Metadata:
                 kwargs: {kwargs}
-
-
-
-
                 """,
                 "cyan",
                 attrs=["bold", "underline"],
@@ -271,6 +410,7 @@ class SequentialWorkflow:
         )
 
     def workflow_shutdown(self, **kwargs) -> None:
+        """Shuts down the workflow."""
         print(
             colored(
                 """
@@ -281,24 +421,35 @@ class SequentialWorkflow:
         )
 
     def add_objective_to_workflow(self, task: str, **kwargs) -> None:
-        print(
-            colored(
-                """
-                Adding Objective to Workflow...""",
-                "green",
-                attrs=["bold", "underline"],
+        """Adds an objective to the workflow."""
+        try:
+            print(
+                colored(
+                    """
+                    Adding Objective to Workflow...""",
+                    "green",
+                    attrs=["bold", "underline"],
+                )
             )
-        )
 
-        task = Task(
-            description=task,
-            flow=kwargs["flow"],
-            args=list(kwargs["args"]),
-            kwargs=kwargs["kwargs"],
-        )
-        self.tasks.append(task)
+            task = Task(
+                description=task,
+                agent=kwargs["agent"],
+                args=list(kwargs["args"]),
+                kwargs=kwargs["kwargs"],
+            )
+            self.tasks.append(task)
+        except Exception as error:
+            print(
+                colored(
+                    f"Error adding objective to workflow: {error}",
+                    "red",
+                )
+            )
 
-    def load_workflow_state(self, filepath: str = None, **kwargs) -> None:
+    def load_workflow_state(
+        self, filepath: str = None, **kwargs
+    ) -> None:
         """
         Loads the workflow state from a json file and restores the workflow state.
 
@@ -316,29 +467,37 @@ class SequentialWorkflow:
         >>> workflow.load_workflow_state("sequential_workflow_state.json")
 
         """
-        filepath = filepath or self.restore_state_filepath
-
-        with open(filepath, "r") as f:
-            state = json.load(f)
-            self.max_loops = state["max_loops"]
-            self.tasks = []
-            for task_state in state["tasks"]:
-                task = Task(
-                    description=task_state["description"],
-                    flow=task_state["flow"],
-                    args=task_state["args"],
-                    kwargs=task_state["kwargs"],
-                    result=task_state["result"],
-                    history=task_state["history"],
+        try:
+            filepath = filepath or self.restore_state_filepath
+
+            with open(filepath, "r") as f:
+                state = json.load(f)
+                self.max_loops = state["max_loops"]
+                self.tasks = []
+                for task_state in state["tasks"]:
+                    task = Task(
+                        description=task_state["description"],
+                        agent=task_state["agent"],
+                        args=task_state["args"],
+                        kwargs=task_state["kwargs"],
+                        result=task_state["result"],
+                        history=task_state["history"],
+                    )
+                    self.tasks.append(task)
+        except Exception as error:
+            print(
+                colored(
+                    f"Error loading workflow state: {error}",
+                    "red",
                 )
-                self.tasks.append(task)
+            )
 
     def run(self) -> None:
         """
         Run the workflow.
 
         Raises:
-            ValueError: If a Flow instance is used as a task and the 'task' argument is not provided.
+            ValueError: If a Agent instance is used as a task and the 'task' argument is not provided.
 
         """
         try:
@@ -347,29 +506,34 @@ class SequentialWorkflow:
                 for task in self.tasks:
                     # Check if the current task can be executed
                     if task.result is None:
-                        # Check if the flow is a Flow and a 'task' argument is needed
-                        if isinstance(task.flow, Flow):
+                        # Check if the agent is a Agent and a 'task' argument is needed
+                        if isinstance(task.agent, Agent):
                             # Ensure that 'task' is provided in the kwargs
                             if "task" not in task.kwargs:
                                 raise ValueError(
-                                    "The 'task' argument is required for the Flow flow"
-                                    f" execution in '{task.description}'"
+                                    "The 'task' argument is required"
+                                    " for the Agent agent execution"
+                                    f" in '{task.description}'"
                                 )
                             # Separate the 'task' argument from other kwargs
                             flow_task_arg = task.kwargs.pop("task")
-                            task.result = task.flow.run(
-                                flow_task_arg, *task.args, **task.kwargs
+                            task.result = task.agent.run(
+                                flow_task_arg,
+                                *task.args,
+                                **task.kwargs,
                             )
                         else:
-                            # If it's not a Flow instance, call the flow directly
-                            task.result = task.flow(*task.args, **task.kwargs)
+                            # If it's not a Agent instance, call the agent directly
+                            task.result = task.agent(
+                                *task.args, **task.kwargs
+                            )
 
                         # Pass the result as an argument to the next task if it exists
                         next_task_index = self.tasks.index(task) + 1
                         if next_task_index < len(self.tasks):
                             next_task = self.tasks[next_task_index]
-                            if isinstance(next_task.flow, Flow):
-                                # For Flow flows, 'task' should be a keyword argument
+                            if isinstance(next_task.agent, Agent):
+                                # For Agent flows, 'task' should be a keyword argument
                                 next_task.kwargs["task"] = task.result
                             else:
                                 # For other callable flows, the result is added to args
@@ -377,14 +541,16 @@ class SequentialWorkflow:
 
                         # Autosave the workflow state
                         if self.autosave:
-                            self.save_workflow_state("sequential_workflow_state.json")
+                            self.save_workflow_state(
+                                "sequential_workflow_state.json"
+                            )
         except Exception as e:
             print(
                 colored(
                     (
-                        f"Error initializing the Sequential workflow: {e} try"
-                        " optimizing your inputs like the flow class and task"
-                        " description"
+                        "Error initializing the Sequential workflow:"
+                        f" {e} try optimizing your inputs like the"
+                        " agent class and task description"
                     ),
                     "red",
                     attrs=["bold", "underline"],
@@ -396,41 +562,61 @@ class SequentialWorkflow:
         Asynchronously run the workflow.
 
         Raises:
-            ValueError: If a Flow instance is used as a task and the 'task' argument is not provided.
+            ValueError: If a Agent instance is used as a task and the 'task' argument is not provided.
 
         """
-        for _ in range(self.max_loops):
-            for task in self.tasks:
-                # Check if the current task can be executed
-                if task.result is None:
-                    # Check if the flow is a Flow and a 'task' argument is needed
-                    if isinstance(task.flow, Flow):
-                        # Ensure that 'task' is provided in the kwargs
-                        if "task" not in task.kwargs:
-                            raise ValueError(
-                                "The 'task' argument is required for the Flow flow"
-                                f" execution in '{task.description}'"
+        try:
+            for _ in range(self.max_loops):
+                for task in self.tasks:
+                    # Check if the current task can be executed
+                    if task.result is None:
+                        # Check if the agent is a Agent and a 'task' argument is needed
+                        if isinstance(task.agent, Agent):
+                            # Ensure that 'task' is provided in the kwargs
+                            if "task" not in task.kwargs:
+                                raise ValueError(
+                                    "The 'task' argument is required"
+                                    " for the Agent agent execution"
+                                    f" in '{task.description}'"
+                                )
+                            # Separate the 'task' argument from other kwargs
+                            flow_task_arg = task.kwargs.pop("task")
+                            task.result = await task.agent.arun(
+                                flow_task_arg,
+                                *task.args,
+                                **task.kwargs,
                             )
-                        # Separate the 'task' argument from other kwargs
-                        flow_task_arg = task.kwargs.pop("task")
-                        task.result = await task.flow.arun(
-                            flow_task_arg, *task.args, **task.kwargs
-                        )
-                    else:
-                        # If it's not a Flow instance, call the flow directly
-                        task.result = await task.flow(*task.args, **task.kwargs)
-
-                    # Pass the result as an argument to the next task if it exists
-                    next_task_index = self.tasks.index(task) + 1
-                    if next_task_index < len(self.tasks):
-                        next_task = self.tasks[next_task_index]
-                        if isinstance(next_task.flow, Flow):
-                            # For Flow flows, 'task' should be a keyword argument
-                            next_task.kwargs["task"] = task.result
                         else:
-                            # For other callable flows, the result is added to args
-                            next_task.args.insert(0, task.result)
+                            # If it's not a Agent instance, call the agent directly
+                            task.result = await task.agent(
+                                *task.args, **task.kwargs
+                            )
+
+                        # Pass the result as an argument to the next task if it exists
+                        next_task_index = self.tasks.index(task) + 1
+                        if next_task_index < len(self.tasks):
+                            next_task = self.tasks[next_task_index]
+                            if isinstance(next_task.agent, Agent):
+                                # For Agent flows, 'task' should be a keyword argument
+                                next_task.kwargs["task"] = task.result
+                            else:
+                                # For other callable flows, the result is added to args
+                                next_task.args.insert(0, task.result)
 
-                    # Autosave the workflow state
-                    if self.autosave:
-                        self.save_workflow_state("sequential_workflow_state.json")
+                        # Autosave the workflow state
+                        if self.autosave:
+                            self.save_workflow_state(
+                                "sequential_workflow_state.json"
+                            )
+        except Exception as e:
+            print(
+                colored(
+                    (
+                        "Error initializing the Sequential workflow:"
+                        f" {e} try optimizing your inputs like the"
+                        " agent class and task description"
+                    ),
+                    "red",
+                    attrs=["bold", "underline"],
+                )
+            )
diff --git a/swarms/structs/task.py b/swarms/structs/task.py
new file mode 100644
index 00000000..8c6e6adc
--- /dev/null
+++ b/swarms/structs/task.py
@@ -0,0 +1,132 @@
+from dataclass import dataclass, field
+from swarms.structs.agent import Agent
+from typing import Optional
+from typing import List, Dict, Any, Sequence
+
+
+@dataclass
+class Task:
+    """
+    Task is a unit of work that can be executed by a set of agents.
+
+    A task is defined by a task name and a set of agents that can execute the task.
+    The task can also have a set of dependencies, which are the names of other tasks
+    that must be executed before this task can be executed.
+
+    Args:
+        id (str): The name of the task.
+        description (Optional[str]): A description of the task.
+        task (str): The name of the task.
+        result (Any): The result of the task.
+        agents (Sequence[Agent]): A list of agents that can execute the task.
+        dependencies (List[str], optional): A list of task names that must be executed before this task can be executed. Defaults to [].
+        args (List[Any], optional): A list of arguments to pass to the agents. Defaults to field(default_factory=list).
+        kwargs (List[Any], optional): A list of keyword arguments to pass to the agents. Defaults to field(default_factory=list).
+
+    Methods:
+        execute: Executes the task by passing the results of the parent tasks to the agents.
+
+    Examples:
+    import os
+    from swarms.models import OpenAIChat
+    from swarms.structs import Agent
+    from swarms.structs.sequential_workflow import SequentialWorkflow
+    from dotenv import load_dotenv
+
+    load_dotenv()
+
+    # Load the environment variables
+    api_key = os.getenv("OPENAI_API_KEY")
+
+
+    # Initialize the language agent
+    llm = OpenAIChat(
+        openai_api_key=api_key,
+        temperature=0.5,
+        max_tokens=3000,
+    )
+
+
+    # Initialize the agent with the language agent
+    agent1 = Agent(llm=llm, max_loops=1)
+
+    # Create another agent for a different task
+    agent2 = Agent(llm=llm, max_loops=1)
+
+    # Create the workflow
+    workflow = SequentialWorkflow(max_loops=1)
+
+    # Add tasks to the workflow
+    workflow.add(
+        agent1, "Generate a 10,000 word blog on health and wellness.",
+    )
+
+    # Suppose the next task takes the output of the first task as input
+    workflow.add(
+        agent2, "Summarize the generated blog",
+    )
+
+    # Run the workflow
+    workflow.run()
+
+    # Output the results
+    for task in workflow.tasks:
+        print(f"Task: {task.description}, Result: {task.result}")
+
+    """
+
+    def __init__(
+        self,
+        id: str,
+        description: Optional[str],
+        task: str,
+        result: Any,
+        agents: Sequence[Agent],
+        dependencies: List[str] = [],
+        args: List[Any] = field(default_factory=list),
+        kwargs: List[Any] = field(default_factory=list),
+    ):
+        self.id = id
+        self.description = description
+        self.task = task
+        self.result = result
+        self.agents = agents
+        self.dependencies = dependencies
+        self.results = []
+        self.args = args
+        self.kwargs = kwargs
+
+    def execute(self, parent_results: Dict[str, Any]):
+        """Executes the task by passing the results of the parent tasks to the agents.
+
+        Args:
+            parent_results (Dict[str, Any]): A dictionary of task names and their results.
+
+        Examples:
+        """
+        args = [parent_results[dep] for dep in self.dependencies]
+        for agent in self.agents:
+            if isinstance(agent, Agent):
+                if "prompt" in self.kwargs:
+                    self.kwargs["prompt"] += (
+                        f"\n\nPrevious output: {self.results[-1]}"
+                        if self.results
+                        else ""
+                    )
+                else:
+                    self.kwargs["prompt"] = (
+                        f"Main task: {self.description}"
+                        + (
+                            f"\n\nPrevious output: {self.results[-1]}"
+                            if self.results
+                            else ""
+                        )
+                    )
+                result = agent.run(
+                    self.description, *args, **self.kwargs
+                )
+            else:
+                result = agent(self.description, *args, **self.kwargs)
+            self.results.append(result)
+            args = [result]
+            self.history.append(result)
diff --git a/swarms/swarms/base.py b/swarms/swarms/base.py
index e99c9b38..15238a8a 100644
--- a/swarms/swarms/base.py
+++ b/swarms/swarms/base.py
@@ -117,7 +117,9 @@ class AbstractSwarm(ABC):
         pass
 
     @abstractmethod
-    def broadcast(self, message: str, sender: Optional["AbstractWorker"] = None):
+    def broadcast(
+        self, message: str, sender: Optional["AbstractWorker"] = None
+    ):
         """Broadcast a message to all workers"""
         pass
 
@@ -142,7 +144,9 @@ class AbstractSwarm(ABC):
         pass
 
     @abstractmethod
-    def autoscaler(self, num_workers: int, worker: ["AbstractWorker"]):
+    def autoscaler(
+        self, num_workers: int, worker: ["AbstractWorker"]
+    ):
         """Autoscaler that acts like kubernetes for autonomous agents"""
         pass
 
@@ -157,7 +161,9 @@ class AbstractSwarm(ABC):
         pass
 
     @abstractmethod
-    def assign_task(self, worker: "AbstractWorker", task: Any) -> Dict:
+    def assign_task(
+        self, worker: "AbstractWorker", task: Any
+    ) -> Dict:
         """Assign a task to a worker"""
         pass
 
diff --git a/swarms/swarms/dialogue_simulator.py b/swarms/swarms/dialogue_simulator.py
index ec86c414..b5a07d7b 100644
--- a/swarms/swarms/dialogue_simulator.py
+++ b/swarms/swarms/dialogue_simulator.py
@@ -16,14 +16,19 @@ class DialogueSimulator:
     Usage:
     ------
     >>> from swarms import DialogueSimulator
-    >>> from swarms.structs.flow import Flow
-    >>> agents = Flow()
-    >>> agents1 = Flow()
+    >>> from swarms.structs.agent import Agent
+    >>> agents = Agent()
+    >>> agents1 = Agent()
     >>> model = DialogueSimulator([agents, agents1], max_iters=10, name="test")
     >>> model.run("test")
     """
 
-    def __init__(self, agents: List[Callable], max_iters: int = 10, name: str = None):
+    def __init__(
+        self,
+        agents: List[Callable],
+        max_iters: int = 10,
+        name: str = None,
+    ):
         self.agents = agents
         self.max_iters = max_iters
         self.name = name
@@ -45,7 +50,8 @@ class DialogueSimulator:
 
                 for receiver in self.agents:
                     message_history = (
-                        f"Speaker Name: {speaker.name} and message: {speaker_message}"
+                        f"Speaker Name: {speaker.name} and message:"
+                        f" {speaker_message}"
                     )
                     receiver.run(message_history)
 
@@ -56,7 +62,10 @@ class DialogueSimulator:
             print(f"Error running dialogue simulator: {error}")
 
     def __repr__(self):
-        return f"DialogueSimulator({self.agents}, {self.max_iters}, {self.name})"
+        return (
+            f"DialogueSimulator({self.agents}, {self.max_iters},"
+            f" {self.name})"
+        )
 
     def save_state(self):
         """Save the state of the dialogue simulator"""
diff --git a/swarms/swarms/god_mode.py b/swarms/swarms/god_mode.py
index e75d81d2..29178b2c 100644
--- a/swarms/swarms/god_mode.py
+++ b/swarms/swarms/god_mode.py
@@ -64,7 +64,12 @@ class GodMode:
             table.append([f"LLM {i+1}", response])
         print(
             colored(
-                tabulate(table, headers=["LLM", "Response"], tablefmt="pretty"), "cyan"
+                tabulate(
+                    table,
+                    headers=["LLM", "Response"],
+                    tablefmt="pretty",
+                ),
+                "cyan",
             )
         )
 
@@ -83,7 +88,12 @@ class GodMode:
             table.append([f"LLM {i+1}", response])
         print(
             colored(
-                tabulate(table, headers=["LLM", "Response"], tablefmt="pretty"), "cyan"
+                tabulate(
+                    table,
+                    headers=["LLM", "Response"],
+                    tablefmt="pretty",
+                ),
+                "cyan",
             )
         )
 
@@ -115,11 +125,17 @@ class GodMode:
             print(f"{i + 1}. {task}")
         print("\nLast Responses:")
         table = [
-            [f"LLM {i+1}", response] for i, response in enumerate(self.last_responses)
+            [f"LLM {i+1}", response]
+            for i, response in enumerate(self.last_responses)
         ]
         print(
             colored(
-                tabulate(table, headers=["LLM", "Response"], tablefmt="pretty"), "cyan"
+                tabulate(
+                    table,
+                    headers=["LLM", "Response"],
+                    tablefmt="pretty",
+                ),
+                "cyan",
             )
         )
 
@@ -137,7 +153,8 @@ class GodMode:
         """Asynchronous run the task string"""
         loop = asyncio.get_event_loop()
         futures = [
-            loop.run_in_executor(None, lambda llm: llm(task), llm) for llm in self.llms
+            loop.run_in_executor(None, lambda llm: llm(task), llm)
+            for llm in self.llms
         ]
         for response in await asyncio.gather(*futures):
             print(response)
@@ -145,13 +162,18 @@ class GodMode:
     def concurrent_run(self, task: str) -> List[str]:
         """Synchronously run the task on all llms and collect responses"""
         with ThreadPoolExecutor() as executor:
-            future_to_llm = {executor.submit(llm, task): llm for llm in self.llms}
+            future_to_llm = {
+                executor.submit(llm, task): llm for llm in self.llms
+            }
             responses = []
             for future in as_completed(future_to_llm):
                 try:
                     responses.append(future.result())
                 except Exception as error:
-                    print(f"{future_to_llm[future]} generated an exception: {error}")
+                    print(
+                        f"{future_to_llm[future]} generated an"
+                        f" exception: {error}"
+                    )
         self.last_responses = responses
         self.task_history.append(task)
         return responses
diff --git a/swarms/swarms/groupchat.py b/swarms/swarms/groupchat.py
index 5cff3263..76f287bc 100644
--- a/swarms/swarms/groupchat.py
+++ b/swarms/swarms/groupchat.py
@@ -1,7 +1,7 @@
 import logging
 from dataclasses import dataclass
 from typing import Dict, List
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 
 logger = logging.getLogger(__name__)
 
@@ -12,19 +12,19 @@ class GroupChat:
     A group chat class that contains a list of agents and the maximum number of rounds.
 
     Args:
-        agents: List[Flow]
+        agents: List[Agent]
         messages: List[Dict]
         max_round: int
         admin_name: str
 
     Usage:
     >>> from swarms import GroupChat
-    >>> from swarms.structs.flow import Flow
-    >>> agents = Flow()
+    >>> from swarms.structs.agent import Agent
+    >>> agents = Agent()
 
     """
 
-    agents: List[Flow]
+    agents: List[Agent]
     messages: List[Dict]
     max_round: int = 10
     admin_name: str = "Admin"  # the name of the admin agent
@@ -38,16 +38,21 @@ class GroupChat:
         """Reset the group chat."""
         self.messages.clear()
 
-    def agent_by_name(self, name: str) -> Flow:
+    def agent_by_name(self, name: str) -> Agent:
         """Find an agent whose name is contained within the given 'name' string."""
         for agent in self.agents:
             if agent.name in name:
                 return agent
-        raise ValueError(f"No agent found with a name contained in '{name}'.")
+        raise ValueError(
+            f"No agent found with a name contained in '{name}'."
+        )
 
-    def next_agent(self, agent: Flow) -> Flow:
+    def next_agent(self, agent: Agent) -> Agent:
         """Return the next agent in the list."""
-        return self.agents[(self.agent_names.index(agent.name) + 1) % len(self.agents)]
+        return self.agents[
+            (self.agent_names.index(agent.name) + 1)
+            % len(self.agents)
+        ]
 
     def select_speaker_msg(self):
         """Return the message for selecting the next speaker."""
@@ -59,7 +64,7 @@ class GroupChat:
         Then select the next role from {self.agent_names} to play. Only return the role.
         """
 
-    def select_speaker(self, last_speaker: Flow, selector: Flow):
+    def select_speaker(self, last_speaker: Agent, selector: Agent):
         """Select the next speaker."""
         selector.update_system_message(self.select_speaker_msg())
 
@@ -67,8 +72,8 @@ class GroupChat:
         n_agents = len(self.agent_names)
         if n_agents < 3:
             logger.warning(
-                f"GroupChat is underpopulated with {n_agents} agents. Direct"
-                " communication would be more efficient."
+                f"GroupChat is underpopulated with {n_agents} agents."
+                " Direct communication would be more efficient."
             )
 
         name = selector.generate_reply(
@@ -78,8 +83,9 @@ class GroupChat:
                     {
                         "role": "system",
                         "content": (
-                            "Read the above conversation. Then select the next most"
-                            f" suitable role from {self.agent_names} to play. Only"
+                            "Read the above conversation. Then"
+                            " select the next most suitable role"
+                            f" from {self.agent_names} to play. Only"
                             " return the role."
                         ),
                     }
@@ -93,13 +99,18 @@ class GroupChat:
 
     def _participant_roles(self):
         return "\n".join(
-            [f"{agent.name}: {agent.system_message}" for agent in self.agents]
+            [
+                f"{agent.name}: {agent.system_message}"
+                for agent in self.agents
+            ]
         )
 
     def format_history(self, messages: List[Dict]) -> str:
         formatted_messages = []
         for message in messages:
-            formatted_message = f"'{message['role']}:{message['content']}"
+            formatted_message = (
+                f"'{message['role']}:{message['content']}"
+            )
             formatted_messages.append(formatted_message)
         return "\n".join(formatted_messages)
 
@@ -110,23 +121,25 @@ class GroupChatManager:
 
     Args:
         groupchat: GroupChat
-        selector: Flow
+        selector: Agent
 
     Usage:
     >>> from swarms import GroupChatManager
-    >>> from swarms.structs.flow import Flow
-    >>> agents = Flow()
+    >>> from swarms.structs.agent import Agent
+    >>> agents = Agent()
     >>> output = GroupChatManager(agents, lambda x: x)
 
 
     """
 
-    def __init__(self, groupchat: GroupChat, selector: Flow):
+    def __init__(self, groupchat: GroupChat, selector: Agent):
         self.groupchat = groupchat
         self.selector = selector
 
     def __call__(self, task: str):
-        self.groupchat.messages.append({"role": self.selector.name, "content": task})
+        self.groupchat.messages.append(
+            {"role": self.selector.name, "content": task}
+        )
         for i in range(self.groupchat.max_round):
             speaker = self.groupchat.select_speaker(
                 last_speaker=self.selector, selector=self.selector
diff --git a/swarms/swarms/multi_agent_collab.py b/swarms/swarms/multi_agent_collab.py
index ce5a0dd6..64b030d0 100644
--- a/swarms/swarms/multi_agent_collab.py
+++ b/swarms/swarms/multi_agent_collab.py
@@ -5,7 +5,7 @@ from typing import List
 import tenacity
 from langchain.output_parsers import RegexParser
 
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 from swarms.utils.logger import logger
 
 
@@ -13,8 +13,8 @@ from swarms.utils.logger import logger
 class BidOutputParser(RegexParser):
     def get_format_instructions(self) -> str:
         return (
-            "Your response should be an integrater delimited by angled brackets like"
-            " this: <int>"
+            "Your response should be an integrater delimited by"
+            " angled brackets like this: <int>"
         )
 
 
@@ -23,32 +23,25 @@ bid_parser = BidOutputParser(
 )
 
 
-def select_next_speaker_director(step: int, agents, director) -> int:
-    # if the step if even => director
-    # => director selects next speaker
-    if step % 2 == 1:
-        idx = 0
-    else:
-        idx = director.select_next_speaker() + 1
-    return idx
-
-
-# Define a selection function
-def select_speaker_round_table(step: int, agents) -> int:
-    # This function selects the speaker in a round-robin fashion
-    return step % len(agents)
-
-
 # main
 class MultiAgentCollaboration:
     """
     Multi-agent collaboration class.
 
     Attributes:
-        agents (List[Flow]): The agents in the collaboration.
+        agents (List[Agent]): The agents in the collaboration.
         selection_function (callable): The function that selects the next speaker.
             Defaults to select_next_speaker.
         max_iters (int): The maximum number of iterations. Defaults to 10.
+        autosave (bool): Whether to autosave the state of all agents. Defaults to True.
+        saved_file_path_name (str): The path to the saved file. Defaults to
+            "multi_agent_collab.json".
+        stopping_token (str): The token that stops the collaboration. Defaults to
+            "<DONE>".
+        results (list): The results of the collaboration. Defaults to [].
+        logger (logging.Logger): The logger. Defaults to logger.
+        logging (bool): Whether to log the collaboration. Defaults to True.
+
 
     Methods:
         reset: Resets the state of all agents.
@@ -62,18 +55,40 @@ class MultiAgentCollaboration:
 
 
     Usage:
-    >>> from swarms.models import MultiAgentCollaboration
-    >>> from swarms.models import Flow
     >>> from swarms.models import OpenAIChat
-    >>> from swarms.models import Anthropic
-
+    >>> from swarms.structs import Agent
+    >>> from swarms.swarms.multi_agent_collab import MultiAgentCollaboration
+    >>>
+    >>> # Initialize the language model
+    >>> llm = OpenAIChat(
+    >>>     temperature=0.5,
+    >>> )
+    >>>
+    >>>
+    >>> ## Initialize the workflow
+    >>> agent = Agent(llm=llm, max_loops=1, dashboard=True)
+    >>>
+    >>> # Run the workflow on a task
+    >>> out = agent.run("Generate a 10,000 word blog on health and wellness.")
+    >>>
+    >>> # Initialize the multi-agent collaboration
+    >>> swarm = MultiAgentCollaboration(
+    >>>     agents=[agent],
+    >>>     max_iters=4,
+    >>> )
+    >>>
+    >>> # Run the multi-agent collaboration
+    >>> swarm.run()
+    >>>
+    >>> # Format the results of the multi-agent collaboration
+    >>> swarm.format_results(swarm.results)
 
     """
 
     def __init__(
         self,
-        agents: List[Flow],
-        selection_function: callable = select_next_speaker_director,
+        agents: List[Agent],
+        selection_function: callable = None,
         max_iters: int = 10,
         autosave: bool = True,
         saved_file_path_name: str = "multi_agent_collab.json",
@@ -102,13 +117,15 @@ class MultiAgentCollaboration:
             agent.run(f"Name {name} and message: {message}")
         self._step += 1
 
-    def inject_agent(self, agent: Flow):
+    def inject_agent(self, agent: Agent):
         """Injects an agent into the multi-agent collaboration."""
         self.agents.append(agent)
 
     def step(self) -> tuple[str, str]:
         """Steps through the multi-agent collaboration."""
-        speaker_idx = self.select_next_speaker(self._step, self.agents)
+        speaker_idx = self.select_next_speaker(
+            self._step, self.agents
+        )
         speaker = self.agents[speaker_idx]
         message = speaker.send()
         message = speaker.send()
@@ -131,7 +148,8 @@ class MultiAgentCollaboration:
         wait=tenacity.wait_none(),
         retry=tenacity.retry_if_exception_type(ValueError),
         before_sleep=lambda retry_state: print(
-            f"ValueError occured: {retry_state.outcome.exception()}, retying..."
+            f"ValueError occured: {retry_state.outcome.exception()},"
+            " retying..."
         ),
         retry_error_callback=lambda retry_state: 0,
     )
@@ -152,7 +170,9 @@ class MultiAgentCollaboration:
             bid = self.ask_for_bid(agent)
             bids.append(bid)
         max_value = max(bids)
-        max_indices = [i for i, x in enumerate(bids) if x == max_value]
+        max_indices = [
+            i for i, x in enumerate(bids) if x == max_value
+        ]
         idx = random.choice(max_indices)
         return idx
 
@@ -161,11 +181,12 @@ class MultiAgentCollaboration:
         wait=tenacity.wait_none(),
         retry=tenacity.retry_if_exception_type(ValueError),
         before_sleep=lambda retry_state: print(
-            f"ValueError occured: {retry_state.outcome.exception()}, retying..."
+            f"ValueError occured: {retry_state.outcome.exception()},"
+            " retying..."
         ),
         retry_error_callback=lambda retry_state: 0,
     )
-    def run(self):
+    def run_director(self, task: str):
         """Runs the multi-agent collaboration."""
         n = 0
         self.reset()
@@ -179,10 +200,87 @@ class MultiAgentCollaboration:
             print("\n")
             n += 1
 
+    def select_next_speaker_roundtable(
+        self, step: int, agents: List[Agent]
+    ) -> int:
+        """Selects the next speaker."""
+        return step % len(agents)
+
+    def select_next_speaker_director(
+        step: int, agents: List[Agent], director
+    ) -> int:
+        # if the step if even => director
+        # => director selects next speaker
+        if step % 2 == 1:
+            idx = 0
+        else:
+            idx = director.select_next_speaker() + 1
+        return idx
+
+    # def run(self, task: str):
+    #     """Runs the multi-agent collaboration."""
+    #     for step in range(self.max_iters):
+    #         speaker_idx = self.select_next_speaker_roundtable(step, self.agents)
+    #         speaker = self.agents[speaker_idx]
+    #         result = speaker.run(task)
+    #         self.results.append({"agent": speaker, "response": result})
+
+    #         if self.autosave:
+    #             self.save_state()
+    #         if result == self.stopping_token:
+    #             break
+    #     return self.results
+
+    # def run(self, task: str):
+    #     for _ in range(self.max_iters):
+    #         for step, agent, in enumerate(self.agents):
+    #             result = agent.run(task)
+    #             self.results.append({"agent": agent, "response": result})
+    #             if self.autosave:
+    #                 self.save_state()
+    #             if result == self.stopping_token:
+    #                 break
+
+    #     return self.results
+
+    # def run(self, task: str):
+    #     conversation = task
+    #     for _ in range(self.max_iters):
+    #         for agent in self.agents:
+    #             result = agent.run(conversation)
+    #             self.results.append({"agent": agent, "response": result})
+    #             conversation = result
+
+    #             if self.autosave:
+    #                 self.save()
+    #             if result == self.stopping_token:
+    #                 break
+    #     return self.results
+
+    def run(self, task: str):
+        conversation = task
+        for _ in range(self.max_iters):
+            for agent in self.agents:
+                result = agent.run(conversation)
+                self.results.append(
+                    {"agent": agent, "response": result}
+                )
+                conversation += result
+
+                if self.autosave:
+                    self.save_state()
+                if result == self.stopping_token:
+                    break
+
+        return self.results
+
     def format_results(self, results):
         """Formats the results of the run method"""
         formatted_results = "\n".join(
-            [f"{result['agent']} responded: {result['response']}" for result in results]
+            [
+                f"{result['agent']} responded: {result['response']}"
+                for result in results
+            ]
         )
         return formatted_results
 
@@ -208,13 +306,20 @@ class MultiAgentCollaboration:
         return state
 
     def __repr__(self):
-        return f"MultiAgentCollaboration(agents={self.agents}, selection_function={self.select_next_speaker}, max_iters={self.max_iters}, autosave={self.autosave}, saved_file_path_name={self.saved_file_path_name})"
+        return (
+            f"MultiAgentCollaboration(agents={self.agents},"
+            f" selection_function={self.select_next_speaker},"
+            f" max_iters={self.max_iters}, autosave={self.autosave},"
+            f" saved_file_path_name={self.saved_file_path_name})"
+        )
 
     def performance(self):
         """Tracks and reports the performance of each agent"""
         performance_data = {}
         for agent in self.agents:
-            performance_data[agent.name] = agent.get_performance_metrics()
+            performance_data[agent.name] = (
+                agent.get_performance_metrics()
+            )
         return performance_data
 
     def set_interaction_rules(self, rules):
diff --git a/swarms/swarms/orchestrate.py b/swarms/swarms/orchestrate.py
index f522911b..387c32e4 100644
--- a/swarms/swarms/orchestrate.py
+++ b/swarms/swarms/orchestrate.py
@@ -111,19 +111,25 @@ class Orchestrator:
 
         self.chroma_client = chromadb.Client()
 
-        self.collection = self.chroma_client.create_collection(name=collection_name)
+        self.collection = self.chroma_client.create_collection(
+            name=collection_name
+        )
 
         self.current_tasks = {}
 
         self.lock = threading.Lock()
         self.condition = threading.Condition(self.lock)
-        self.executor = ThreadPoolExecutor(max_workers=len(agent_list))
+        self.executor = ThreadPoolExecutor(
+            max_workers=len(agent_list)
+        )
 
         self.embed_func = embed_func if embed_func else self.embed
 
     # @abstractmethod
 
-    def assign_task(self, agent_id: int, task: Dict[str, Any]) -> None:
+    def assign_task(
+        self, agent_id: int, task: Dict[str, Any]
+    ) -> None:
         """Assign a task to a specific agent"""
 
         while True:
@@ -148,13 +154,14 @@ class Orchestrator:
                 )
 
                 logging.info(
-                    f"Task {id(str)} has been processed by agent {id(agent)} with"
+                    f"Task {id(str)} has been processed by agent"
+                    f" {id(agent)} with"
                 )
 
             except Exception as error:
                 logging.error(
-                    f"Failed to process task {id(task)} by agent {id(agent)}. Error:"
-                    f" {error}"
+                    f"Failed to process task {id(task)} by agent"
+                    f" {id(agent)}. Error: {error}"
                 )
             finally:
                 with self.condition:
@@ -175,12 +182,15 @@ class Orchestrator:
 
         try:
             # Query the vector database for documents created by the agents
-            results = self.collection.query(query_texts=[str(agent_id)], n_results=10)
+            results = self.collection.query(
+                query_texts=[str(agent_id)], n_results=10
+            )
 
             return results
         except Exception as e:
             logging.error(
-                f"Failed to retrieve results from agent {agent_id}. Error {e}"
+                f"Failed to retrieve results from agent {agent_id}."
+                f" Error {e}"
             )
             raise
 
@@ -196,7 +206,9 @@ class Orchestrator:
             )
 
         except Exception as e:
-            logging.error(f"Failed to update the vector database. Error: {e}")
+            logging.error(
+                f"Failed to update the vector database. Error: {e}"
+            )
             raise
 
     # @abstractmethod
@@ -209,10 +221,15 @@ class Orchestrator:
         """append the result of the swarm to a specifici collection in the database"""
 
         try:
-            self.collection.add(documents=[result], ids=[str(id(result))])
+            self.collection.add(
+                documents=[result], ids=[str(id(result))]
+            )
 
         except Exception as e:
-            logging.error(f"Failed to append the agent output to database. Error: {e}")
+            logging.error(
+                "Failed to append the agent output to database."
+                f" Error: {e}"
+            )
             raise
 
     def run(self, objective: str):
@@ -226,13 +243,17 @@ class Orchestrator:
 
             results = [
                 self.assign_task(agent_id, task)
-                for agent_id, task in zip(range(len(self.agents)), self.task_queue)
+                for agent_id, task in zip(
+                    range(len(self.agents)), self.task_queue
+                )
             ]
 
             for result in results:
                 self.append_to_db(result)
 
-            logging.info(f"Successfully ran swarms with results: {results}")
+            logging.info(
+                f"Successfully ran swarms with results: {results}"
+            )
             return results
         except Exception as e:
             logging.error(f"An error occured in swarm: {e}")
@@ -255,7 +276,9 @@ class Orchestrator:
 
         """
 
-        message_vector = self.embed(message, self.api_key, self.model_name)
+        message_vector = self.embed(
+            message, self.api_key, self.model_name
+        )
 
         # store the mesage in the vector database
         self.collection.add(
@@ -264,15 +287,21 @@ class Orchestrator:
             ids=[f"{sender_id}_to_{receiver_id}"],
         )
 
-        self.run(objective=f"chat with agent {receiver_id} about {message}")
+        self.run(
+            objective=f"chat with agent {receiver_id} about {message}"
+        )
 
     def add_agents(self, num_agents: int):
         for _ in range(num_agents):
             self.agents.put(self.agent())
-        self.executor = ThreadPoolExecutor(max_workers=self.agents.qsize())
+        self.executor = ThreadPoolExecutor(
+            max_workers=self.agents.qsize()
+        )
 
     def remove_agents(self, num_agents):
         for _ in range(num_agents):
             if not self.agents.empty():
                 self.agents.get()
-        self.executor = ThreadPoolExecutor(max_workers=self.agents.qsize())
+        self.executor = ThreadPoolExecutor(
+            max_workers=self.agents.qsize()
+        )
diff --git a/swarms/tools/README.md b/swarms/tools/README.md
deleted file mode 100644
index c4e1c002..00000000
--- a/swarms/tools/README.md
+++ /dev/null
@@ -1,114 +0,0 @@
-Here are 20 tools the individual worker swarm nodes can use:
-
-1. Write File Tool: Create a new file and write content to it.
-2. Read File Tool: Open and read the content of an existing file.
-3. Copy File Tool: Duplicate a file.
-4. Delete File Tool: Remove a file.
-5. Rename File Tool: Rename a file.
-6. Web Search Tool: Use a web search engine (like Google or DuckDuckGo) to find information.
-7. API Call Tool: Make requests to APIs.
-8. Process CSV Tool: Load a CSV file and perform operations on it using pandas.
-9. Create Directory Tool: Create a new directory.
-10. List Directory Tool: List all the files in a directory.
-11. Install Package Tool: Install Python packages using pip.
-12. Code Compilation Tool: Compile and run code in different languages.
-13. System Command Tool: Execute system commands.
-14. Image Processing Tool: Perform operations on images (resizing, cropping, etc.).
-15. PDF Processing Tool: Read, write, and manipulate PDF files.
-16. Text Processing Tool: Perform text processing operations like tokenization, stemming, etc.
-17. Email Sending Tool: Send emails.
-18. Database Query Tool: Execute SQL queries on a database.
-19. Data Scraping Tool: Scrape data from web pages.
-20. Version Control Tool: Perform Git operations.
-
-The architecture for these tools involves creating a base `Tool` class that can be extended for each specific tool. The base `Tool` class would define common properties and methods that all tools would use.
-
-The pseudocode for each tool would follow a similar structure:
-
-```
-Class ToolNameTool extends Tool:
-    Define properties specific to the tool
-
-    Method run: 
-        Perform the specific action of the tool
-        Return the result
-```
-
-Here's an example of how you might define the WriteFileTool:
-
-```python
-import os
-from langchain.tools import BaseTool
-
-class WriteFileTool(BaseTool):
-    name = "write_file"
-    description = "Create a new file and write content to it."
-
-    def __init__(self, root_dir: str):
-        self.root_dir = root_dir
-
-    def _run(self, file_name: str, content: str) -> str:
-        """Creates a new file and writes the content."""
-        try:
-            with open(os.path.join(self.root_dir, file_name), 'w') as f:
-                f.write(content)
-            return f"Successfully wrote to {file_name}"
-        except Exception as e:
-            return f"Error: {e}"
-```
-
-This tool takes the name of the file and the content to be written as parameters, writes the content to the file in the specified directory, and returns a success message. In case of any error, it returns the error message. You would follow a similar process to create the other tools.
-
-
-
-
-For completing browser-based tasks, you can use web automation tools. These tools allow you to interact with browsers as if a human user was interacting with it. Here are 20 tasks that individual worker swarm nodes can handle:
-
-1. Open Browser Tool: Open a web browser.
-2. Close Browser Tool: Close the web browser.
-3. Navigate To URL Tool: Navigate to a specific URL.
-4. Fill Form Tool: Fill in a web form with provided data.
-5. Submit Form Tool: Submit a filled form.
-6. Click Button Tool: Click a button on a webpage.
-7. Hover Over Element Tool: Hover over a specific element on a webpage.
-8. Scroll Page Tool: Scroll up or down a webpage.
-9. Navigate Back Tool: Navigate back to the previous page.
-10. Navigate Forward Tool: Navigate forward to the next page.
-11. Refresh Page Tool: Refresh the current page.
-12. Switch Tab Tool: Switch between tabs in a browser.
-13. Capture Screenshot Tool: Capture a screenshot of the current page.
-14. Download File Tool: Download a file from a webpage.
-15. Send Email Tool: Send an email using a web-based email service.
-16. Login Tool: Log in to a website using provided credentials.
-17. Search Website Tool: Perform a search on a website.
-18. Extract Text Tool: Extract text from a webpage.
-19. Extract Image Tool: Extract image(s) from a webpage.
-20. Browser Session Management Tool: Handle creation, usage, and deletion of browser sessions.
-
-You would typically use a library like Selenium, Puppeteer, or Playwright to automate these tasks. Here's an example of how you might define the FillFormTool using Selenium in Python:
-
-```python
-from selenium import webdriver
-from langchain.tools import BaseTool
-
-class FillFormTool(BaseTool):
-    name = "fill_form"
-    description = "Fill in a web form with provided data."
-
-    def _run(self, field_dict: dict) -> str:
-        """Fills a web form with the data in field_dict."""
-        try:
-            driver = webdriver.Firefox()
-            
-            for field_name, field_value in field_dict.items():
-                element = driver.find_element_by_name(field_name)
-                element.send_keys(field_value)
-
-            return "Form filled successfully."
-        except Exception as e:
-            return f"Error: {e}"
-```
-
-In this tool, `field_dict` is a dictionary where the keys are the names of the form fields and the values are the data to be filled in each field. The tool finds each field in the form and fills it with the provided data.
-
-Please note that in a real scenario, you would need to handle the browser driver session more carefully (like closing the driver when it's not needed anymore), and also handle waiting for the page to load and exceptions more thoroughly. This is a simplified example for illustrative purposes.
\ No newline at end of file
diff --git a/swarms/tools/__init__.py b/swarms/tools/__init__.py
index e69de29b..65153867 100644
--- a/swarms/tools/__init__.py
+++ b/swarms/tools/__init__.py
@@ -0,0 +1,3 @@
+from swarms.tools.tool_func_doc_scraper import scrape_tool_func_docs
+
+__all__ = ["scrape_tool_func_docs"]
diff --git a/swarms/tools/autogpt.py b/swarms/tools/autogpt.py
deleted file mode 100644
index cf5450e6..00000000
--- a/swarms/tools/autogpt.py
+++ /dev/null
@@ -1,188 +0,0 @@
-import asyncio
-import os
-from contextlib import contextmanager
-from typing import Optional
-
-import pandas as pd
-import torch
-from langchain.agents import tool
-from langchain.agents.agent_toolkits.pandas.base import create_pandas_dataframe_agent
-from langchain.chains.qa_with_sources.loading import (
-    BaseCombineDocumentsChain,
-)
-from langchain.docstore.document import Document
-from langchain.text_splitter import RecursiveCharacterTextSplitter
-from langchain.tools import BaseTool
-from PIL import Image
-from pydantic import Field
-from transformers import (
-    BlipForQuestionAnswering,
-    BlipProcessor,
-)
-
-from swarms.utils.logger import logger
-
-ROOT_DIR = "./data/"
-
-
-@contextmanager
-def pushd(new_dir):
-    """Context manager for changing the current working directory."""
-    prev_dir = os.getcwd()
-    os.chdir(new_dir)
-    try:
-        yield
-    finally:
-        os.chdir(prev_dir)
-
-
-@tool
-def process_csv(
-    llm, csv_file_path: str, instructions: str, output_path: Optional[str] = None
-) -> str:
-    """Process a CSV by with pandas in a limited REPL.\
- Only use this after writing data to disk as a csv file.\
- Any figures must be saved to disk to be viewed by the human.\
- Instructions should be written in natural language, not code. Assume the dataframe is already loaded."""
-    with pushd(ROOT_DIR):
-        try:
-            df = pd.read_csv(csv_file_path)
-        except Exception as e:
-            return f"Error: {e}"
-        agent = create_pandas_dataframe_agent(llm, df, max_iterations=30, verbose=False)
-        if output_path is not None:
-            instructions += f" Save output to disk at {output_path}"
-        try:
-            result = agent.run(instructions)
-            return result
-        except Exception as e:
-            return f"Error: {e}"
-
-
-async def async_load_playwright(url: str) -> str:
-    """Load the specified URLs using Playwright and parse using BeautifulSoup."""
-    from bs4 import BeautifulSoup
-    from playwright.async_api import async_playwright
-
-    results = ""
-    async with async_playwright() as p:
-        browser = await p.chromium.launch(headless=True)
-        try:
-            page = await browser.new_page()
-            await page.goto(url)
-
-            page_source = await page.content()
-            soup = BeautifulSoup(page_source, "html.parser")
-
-            for script in soup(["script", "style"]):
-                script.extract()
-
-            text = soup.get_text()
-            lines = (line.strip() for line in text.splitlines())
-            chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
-            results = "\n".join(chunk for chunk in chunks if chunk)
-        except Exception as e:
-            results = f"Error: {e}"
-        await browser.close()
-    return results
-
-
-def run_async(coro):
-    event_loop = asyncio.get_event_loop()
-    return event_loop.run_until_complete(coro)
-
-
-@tool
-def browse_web_page(url: str) -> str:
-    """Verbose way to scrape a whole webpage. Likely to cause issues parsing."""
-    return run_async(async_load_playwright(url))
-
-
-def _get_text_splitter():
-    return RecursiveCharacterTextSplitter(
-        # Set a really small chunk size, just to show.
-        chunk_size=500,
-        chunk_overlap=20,
-        length_function=len,
-    )
-
-
-class WebpageQATool(BaseTool):
-    name = "query_webpage"
-    description = (
-        "Browse a webpage and retrieve the information relevant to the question."
-    )
-    text_splitter: RecursiveCharacterTextSplitter = Field(
-        default_factory=_get_text_splitter
-    )
-    qa_chain: BaseCombineDocumentsChain
-
-    def _run(self, url: str, question: str) -> str:
-        """Useful for browsing websites and scraping the text information."""
-        result = browse_web_page.run(url)
-        docs = [Document(page_content=result, metadata={"source": url})]
-        web_docs = self.text_splitter.split_documents(docs)
-        results = []
-        # TODO: Handle this with a MapReduceChain
-        for i in range(0, len(web_docs), 4):
-            input_docs = web_docs[i : i + 4]
-            window_result = self.qa_chain(
-                {"input_documents": input_docs, "question": question},
-                return_only_outputs=True,
-            )
-            results.append(f"Response from window {i} - {window_result}")
-        results_docs = [
-            Document(page_content="\n".join(results), metadata={"source": url})
-        ]
-        return self.qa_chain(
-            {"input_documents": results_docs, "question": question},
-            return_only_outputs=True,
-        )
-
-    async def _arun(self, url: str, question: str) -> str:
-        raise NotImplementedError
-
-
-class EdgeGPTTool:
-    # Initialize the custom tool
-    def __init__(
-        self,
-        model,
-        name="EdgeGPTTool",
-        description="Tool that uses EdgeGPTModel to generate responses",
-    ):
-        super().__init__(name=name, description=description)
-        self.model = model
-
-    def _run(self, prompt):
-        return self.model.__call__(prompt)
-
-
-@tool
-def VQAinference(self, inputs):
-    """
-    Answer Question About The Image, VQA Multi-Modal Worker agent
-    description="useful when you need an answer for a question based on an image. "
-    "like: what is the background color of the last image, how many cats in this figure, what is in this figure. "
-    "The input to this tool should be a comma separated string of two, representing the image_path and the question",
-
-    """
-    device = "cuda:0"
-    torch_dtype = torch.float16 if "cuda" in device else torch.float32
-    processor = BlipProcessor.from_pretrained("Salesforce/blip-vqa-base")
-    model = BlipForQuestionAnswering.from_pretrained(
-        "Salesforce/blip-vqa-base", torch_dtype=torch_dtype
-    ).to(device)
-
-    image_path, question = inputs.split(",")
-    raw_image = Image.open(image_path).convert("RGB")
-    inputs = processor(raw_image, question, return_tensors="pt").to(device, torch_dtype)
-    out = model.generate(**inputs)
-    answer = processor.decode(out[0], skip_special_tokens=True)
-
-    logger.debug(
-        f"\nProcessed VisualQuestionAnswering, Input Image: {image_path}, Input"
-        f" Question: {question}, Output Answer: {answer}"
-    )
-
-    return answer
diff --git a/swarms/tools/mm_models.py b/swarms/tools/mm_models.py
deleted file mode 100644
index 58fe11e5..00000000
--- a/swarms/tools/mm_models.py
+++ /dev/null
@@ -1,271 +0,0 @@
-import os
-import uuid
-
-import numpy as np
-import torch
-from diffusers import (
-    EulerAncestralDiscreteScheduler,
-    StableDiffusionInpaintPipeline,
-    StableDiffusionInstructPix2PixPipeline,
-    StableDiffusionPipeline,
-)
-from PIL import Image
-from transformers import (
-    BlipForConditionalGeneration,
-    BlipForQuestionAnswering,
-    BlipProcessor,
-    CLIPSegForImageSegmentation,
-    CLIPSegProcessor,
-)
-
-from swarms.prompts.prebuild.multi_modal_prompts import IMAGE_PROMPT
-from swarms.tools.tool import tool
-from swarms.utils.logger import logger
-from swarms.utils.main import BaseHandler, get_new_image_name
-
-
-class MaskFormer:
-    def __init__(self, device):
-        print("Initializing MaskFormer to %s" % device)
-        self.device = device
-        self.processor = CLIPSegProcessor.from_pretrained("CIDAS/clipseg-rd64-refined")
-        self.model = CLIPSegForImageSegmentation.from_pretrained(
-            "CIDAS/clipseg-rd64-refined"
-        ).to(device)
-
-    def inference(self, image_path, text):
-        threshold = 0.5
-        min_area = 0.02
-        padding = 20
-        original_image = Image.open(image_path)
-        image = original_image.resize((512, 512))
-        inputs = self.processor(
-            text=text, images=image, padding="max_length", return_tensors="pt"
-        ).to(self.device)
-        with torch.no_grad():
-            outputs = self.model(**inputs)
-        mask = torch.sigmoid(outputs[0]).squeeze().cpu().numpy() > threshold
-        area_ratio = len(np.argwhere(mask)) / (mask.shape[0] * mask.shape[1])
-        if area_ratio < min_area:
-            return None
-        true_indices = np.argwhere(mask)
-        mask_array = np.zeros_like(mask, dtype=bool)
-        for idx in true_indices:
-            padded_slice = tuple(
-                slice(max(0, i - padding), i + padding + 1) for i in idx
-            )
-            mask_array[padded_slice] = True
-        visual_mask = (mask_array * 255).astype(np.uint8)
-        image_mask = Image.fromarray(visual_mask)
-        return image_mask.resize(original_image.size)
-
-
-class ImageEditing:
-    def __init__(self, device):
-        print("Initializing ImageEditing to %s" % device)
-        self.device = device
-        self.mask_former = MaskFormer(device=self.device)
-        self.revision = "fp16" if "cuda" in device else None
-        self.torch_dtype = torch.float16 if "cuda" in device else torch.float32
-        self.inpaint = StableDiffusionInpaintPipeline.from_pretrained(
-            "runwayml/stable-diffusion-inpainting",
-            revision=self.revision,
-            torch_dtype=self.torch_dtype,
-        ).to(device)
-
-    @tool(
-        name="Remove Something From The Photo",
-        description=(
-            "useful when you want to remove and object or something from the photo "
-            "from its description or location. "
-            "The input to this tool should be a comma separated string of two, "
-            "representing the image_path and the object need to be removed. "
-        ),
-    )
-    def inference_remove(self, inputs):
-        image_path, to_be_removed_txt = inputs.split(",")
-        return self.inference_replace(f"{image_path},{to_be_removed_txt},background")
-
-    @tool(
-        name="Replace Something From The Photo",
-        description=(
-            "useful when you want to replace an object from the object description or"
-            " location with another object from its description. The input to this tool"
-            " should be a comma separated string of three, representing the image_path,"
-            " the object to be replaced, the object to be replaced with "
-        ),
-    )
-    def inference_replace(self, inputs):
-        image_path, to_be_replaced_txt, replace_with_txt = inputs.split(",")
-        original_image = Image.open(image_path)
-        original_size = original_image.size
-        mask_image = self.mask_former.inference(image_path, to_be_replaced_txt)
-        updated_image = self.inpaint(
-            prompt=replace_with_txt,
-            image=original_image.resize((512, 512)),
-            mask_image=mask_image.resize((512, 512)),
-        ).images[0]
-        updated_image_path = get_new_image_name(
-            image_path, func_name="replace-something"
-        )
-        updated_image = updated_image.resize(original_size)
-        updated_image.save(updated_image_path)
-
-        logger.debug(
-            f"\nProcessed ImageEditing, Input Image: {image_path}, Replace"
-            f" {to_be_replaced_txt} to {replace_with_txt}, Output Image:"
-            f" {updated_image_path}"
-        )
-
-        return updated_image_path
-
-
-class InstructPix2Pix:
-    def __init__(self, device):
-        print("Initializing InstructPix2Pix to %s" % device)
-        self.device = device
-        self.torch_dtype = torch.float16 if "cuda" in device else torch.float32
-        self.pipe = StableDiffusionInstructPix2PixPipeline.from_pretrained(
-            "timbrooks/instruct-pix2pix",
-            safety_checker=None,
-            torch_dtype=self.torch_dtype,
-        ).to(device)
-        self.pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(
-            self.pipe.scheduler.config
-        )
-
-    @tool(
-        name="Instruct Image Using Text",
-        description=(
-            "useful when you want to the style of the image to be like the text. "
-            "like: make it look like a painting. or make it like a robot. "
-            "The input to this tool should be a comma separated string of two, "
-            "representing the image_path and the text. "
-        ),
-    )
-    def inference(self, inputs):
-        """Change style of image."""
-        logger.debug("===> Starting InstructPix2Pix Inference")
-        image_path, text = inputs.split(",")[0], ",".join(inputs.split(",")[1:])
-        original_image = Image.open(image_path)
-        image = self.pipe(
-            text, image=original_image, num_inference_steps=40, image_guidance_scale=1.2
-        ).images[0]
-        updated_image_path = get_new_image_name(image_path, func_name="pix2pix")
-        image.save(updated_image_path)
-
-        logger.debug(
-            f"\nProcessed InstructPix2Pix, Input Image: {image_path}, Instruct Text:"
-            f" {text}, Output Image: {updated_image_path}"
-        )
-
-        return updated_image_path
-
-
-class Text2Image:
-    def __init__(self, device):
-        print("Initializing Text2Image to %s" % device)
-        self.device = device
-        self.torch_dtype = torch.float16 if "cuda" in device else torch.float32
-        self.pipe = StableDiffusionPipeline.from_pretrained(
-            "runwayml/stable-diffusion-v1-5", torch_dtype=self.torch_dtype
-        )
-        self.pipe.to(device)
-        self.a_prompt = "best quality, extremely detailed"
-        self.n_prompt = (
-            "longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, "
-            "fewer digits, cropped, worst quality, low quality"
-        )
-
-    @tool(
-        name="Generate Image From User Input Text",
-        description=(
-            "useful when you want to generate an image from a user input text and save"
-            " it to a file. like: generate an image of an object or something, or"
-            " generate an image that includes some objects. The input to this tool"
-            " should be a string, representing the text used to generate image. "
-        ),
-    )
-    def inference(self, text):
-        image_filename = os.path.join("image", str(uuid.uuid4())[0:8] + ".png")
-        prompt = text + ", " + self.a_prompt
-        image = self.pipe(prompt, negative_prompt=self.n_prompt).images[0]
-        image.save(image_filename)
-
-        logger.debug(
-            f"\nProcessed Text2Image, Input Text: {text}, Output Image:"
-            f" {image_filename}"
-        )
-
-        return image_filename
-
-
-class VisualQuestionAnswering:
-    def __init__(self, device):
-        print("Initializing VisualQuestionAnswering to %s" % device)
-        self.torch_dtype = torch.float16 if "cuda" in device else torch.float32
-        self.device = device
-        self.processor = BlipProcessor.from_pretrained("Salesforce/blip-vqa-base")
-        self.model = BlipForQuestionAnswering.from_pretrained(
-            "Salesforce/blip-vqa-base", torch_dtype=self.torch_dtype
-        ).to(self.device)
-
-    @tool(
-        name="Answer Question About The Image",
-        description=(
-            "useful when you need an answer for a question based on an image. like:"
-            " what is the background color of the last image, how many cats in this"
-            " figure, what is in this figure. The input to this tool should be a comma"
-            " separated string of two, representing the image_path and the question"
-        ),
-    )
-    def inference(self, inputs):
-        image_path, question = inputs.split(",")
-        raw_image = Image.open(image_path).convert("RGB")
-        inputs = self.processor(raw_image, question, return_tensors="pt").to(
-            self.device, self.torch_dtype
-        )
-        out = self.model.generate(**inputs)
-        answer = self.processor.decode(out[0], skip_special_tokens=True)
-
-        logger.debug(
-            f"\nProcessed VisualQuestionAnswering, Input Image: {image_path}, Input"
-            f" Question: {question}, Output Answer: {answer}"
-        )
-
-        return answer
-
-
-class ImageCaptioning(BaseHandler):
-    def __init__(self, device):
-        print("Initializing ImageCaptioning to %s" % device)
-        self.device = device
-        self.torch_dtype = torch.float16 if "cuda" in device else torch.float32
-        self.processor = BlipProcessor.from_pretrained(
-            "Salesforce/blip-image-captioning-base"
-        )
-        self.model = BlipForConditionalGeneration.from_pretrained(
-            "Salesforce/blip-image-captioning-base", torch_dtype=self.torch_dtype
-        ).to(self.device)
-
-    def handle(self, filename: str):
-        img = Image.open(filename)
-        width, height = img.size
-        ratio = min(512 / width, 512 / height)
-        width_new, height_new = (round(width * ratio), round(height * ratio))
-        img = img.resize((width_new, height_new))
-        img = img.convert("RGB")
-        img.save(filename, "PNG")
-        print(f"Resize image form {width}x{height} to {width_new}x{height_new}")
-
-        inputs = self.processor(Image.open(filename), return_tensors="pt").to(
-            self.device, self.torch_dtype
-        )
-        out = self.model.generate(**inputs)
-        description = self.processor.decode(out[0], skip_special_tokens=True)
-        print(
-            f"\nProcessed ImageCaptioning, Input Image: {filename}, Output Text:"
-            f" {description}"
-        )
-
-        return IMAGE_PROMPT.format(filename=filename, description=description)
diff --git a/swarms/tools/tool.py b/swarms/tools/tool.py
index a5ad3f75..1029a183 100644
--- a/swarms/tools/tool.py
+++ b/swarms/tools/tool.py
@@ -7,7 +7,17 @@ import warnings
 from abc import abstractmethod
 from functools import partial
 from inspect import signature
-from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, Type, Union
+from typing import (
+    Any,
+    Awaitable,
+    Callable,
+    Dict,
+    List,
+    Optional,
+    Tuple,
+    Type,
+    Union,
+)
 
 from langchain.callbacks.base import BaseCallbackManager
 from langchain.callbacks.manager import (
@@ -27,7 +37,11 @@ from pydantic import (
     root_validator,
     validate_arguments,
 )
-from langchain.schema.runnable import Runnable, RunnableConfig, RunnableSerializable
+from langchain.schema.runnable import (
+    Runnable,
+    RunnableConfig,
+    RunnableSerializable,
+)
 
 
 class SchemaAnnotationError(TypeError):
@@ -52,7 +66,11 @@ def _get_filtered_args(
     """Get the arguments from a function's signature."""
     schema = inferred_model.schema()["properties"]
     valid_keys = signature(func).parameters
-    return {k: schema[k] for k in valid_keys if k not in ("run_manager", "callbacks")}
+    return {
+        k: schema[k]
+        for k in valid_keys
+        if k not in ("run_manager", "callbacks")
+    }
 
 
 class _SchemaConfig:
@@ -100,16 +118,21 @@ class ToolException(Exception):
 
 
 class BaseTool(RunnableSerializable[Union[str, Dict], Any]):
-    """Interface LangChain tools must implement."""
+    """Interface swarms tools must implement."""
 
     def __init_subclass__(cls, **kwargs: Any) -> None:
         """Create the definition of the new tool class."""
         super().__init_subclass__(**kwargs)
 
-        args_schema_type = cls.__annotations__.get("args_schema", None)
+        args_schema_type = cls.__annotations__.get(
+            "args_schema", None
+        )
 
         if args_schema_type is not None:
-            if args_schema_type is None or args_schema_type == BaseModel:
+            if (
+                args_schema_type is None
+                or args_schema_type == BaseModel
+            ):
                 # Throw errors for common mis-annotations.
                 # TODO: Use get_args / get_origin and fully
                 # specify valid annotations.
@@ -120,12 +143,12 @@ class ChildTool(BaseTool):
     ..."""
                 name = cls.__name__
                 raise SchemaAnnotationError(
-                    f"Tool definition for {name} must include valid type annotations"
-                    " for argument 'args_schema' to behave as expected.\n"
-                    "Expected annotation of 'Type[BaseModel]'"
-                    f" but got '{args_schema_type}'.\n"
-                    "Expected class looks like:\n"
-                    f"{typehint_mandate}"
+                    f"Tool definition for {name} must include valid"
+                    " type annotations for argument 'args_schema' to"
+                    " behave as expected.\nExpected annotation of"
+                    " 'Type[BaseModel]' but got"
+                    f" '{args_schema_type}'.\nExpected class looks"
+                    f" like:\n{typehint_mandate}"
                 )
 
     name: str
@@ -147,7 +170,9 @@ class ChildTool(BaseTool):
 
     callbacks: Callbacks = Field(default=None, exclude=True)
     """Callbacks to be called during tool execution."""
-    callback_manager: Optional[BaseCallbackManager] = Field(default=None, exclude=True)
+    callback_manager: Optional[BaseCallbackManager] = Field(
+        default=None, exclude=True
+    )
     """Deprecated. Please use callbacks instead."""
     tags: Optional[List[str]] = None
     """Optional list of tags associated with the tool. Defaults to None
@@ -244,7 +269,11 @@ class ChildTool(BaseTool):
         else:
             if input_args is not None:
                 result = input_args.parse_obj(tool_input)
-                return {k: v for k, v in result.dict().items() if k in tool_input}
+                return {
+                    k: v
+                    for k, v in result.dict().items()
+                    if k in tool_input
+                }
         return tool_input
 
     @root_validator()
@@ -252,7 +281,10 @@ class ChildTool(BaseTool):
         """Raise deprecation warning if callback_manager is used."""
         if values.get("callback_manager") is not None:
             warnings.warn(
-                "callback_manager is deprecated. Please use callbacks instead.",
+                (
+                    "callback_manager is deprecated. Please use"
+                    " callbacks instead."
+                ),
                 DeprecationWarning,
             )
             values["callbacks"] = values.pop("callback_manager", None)
@@ -286,7 +318,9 @@ class ChildTool(BaseTool):
             *args,
         )
 
-    def _to_args_and_kwargs(self, tool_input: Union[str, Dict]) -> Tuple[Tuple, Dict]:
+    def _to_args_and_kwargs(
+        self, tool_input: Union[str, Dict]
+    ) -> Tuple[Tuple, Dict]:
         # For backwards compatibility, if run_input is a string,
         # pass as a positional argument.
         if isinstance(tool_input, str):
@@ -323,18 +357,28 @@ class ChildTool(BaseTool):
             self.metadata,
         )
         # TODO: maybe also pass through run_manager is _run supports kwargs
-        new_arg_supported = signature(self._run).parameters.get("run_manager")
+        new_arg_supported = signature(self._run).parameters.get(
+            "run_manager"
+        )
         run_manager = callback_manager.on_tool_start(
             {"name": self.name, "description": self.description},
-            tool_input if isinstance(tool_input, str) else str(tool_input),
+            (
+                tool_input
+                if isinstance(tool_input, str)
+                else str(tool_input)
+            ),
             color=start_color,
             name=run_name,
             **kwargs,
         )
         try:
-            tool_args, tool_kwargs = self._to_args_and_kwargs(parsed_input)
+            tool_args, tool_kwargs = self._to_args_and_kwargs(
+                parsed_input
+            )
             observation = (
-                self._run(*tool_args, run_manager=run_manager, **tool_kwargs)
+                self._run(
+                    *tool_args, run_manager=run_manager, **tool_kwargs
+                )
                 if new_arg_supported
                 else self._run(*tool_args, **tool_kwargs)
             )
@@ -353,11 +397,15 @@ class ChildTool(BaseTool):
                 observation = self.handle_tool_error(e)
             else:
                 raise ValueError(
-                    "Got unexpected type of `handle_tool_error`. Expected bool, str "
-                    f"or callable. Received: {self.handle_tool_error}"
+                    "Got unexpected type of `handle_tool_error`."
+                    " Expected bool, str or callable. Received:"
+                    f" {self.handle_tool_error}"
                 )
             run_manager.on_tool_end(
-                str(observation), color="red", name=self.name, **kwargs
+                str(observation),
+                color="red",
+                name=self.name,
+                **kwargs,
             )
             return observation
         except (Exception, KeyboardInterrupt) as e:
@@ -365,7 +413,10 @@ class ChildTool(BaseTool):
             raise e
         else:
             run_manager.on_tool_end(
-                str(observation), color=color, name=self.name, **kwargs
+                str(observation),
+                color=color,
+                name=self.name,
+                **kwargs,
             )
             return observation
 
@@ -397,19 +448,29 @@ class ChildTool(BaseTool):
             metadata,
             self.metadata,
         )
-        new_arg_supported = signature(self._arun).parameters.get("run_manager")
+        new_arg_supported = signature(self._arun).parameters.get(
+            "run_manager"
+        )
         run_manager = await callback_manager.on_tool_start(
             {"name": self.name, "description": self.description},
-            tool_input if isinstance(tool_input, str) else str(tool_input),
+            (
+                tool_input
+                if isinstance(tool_input, str)
+                else str(tool_input)
+            ),
             color=start_color,
             name=run_name,
             **kwargs,
         )
         try:
             # We then call the tool on the tool input to get an observation
-            tool_args, tool_kwargs = self._to_args_and_kwargs(parsed_input)
+            tool_args, tool_kwargs = self._to_args_and_kwargs(
+                parsed_input
+            )
             observation = (
-                await self._arun(*tool_args, run_manager=run_manager, **tool_kwargs)
+                await self._arun(
+                    *tool_args, run_manager=run_manager, **tool_kwargs
+                )
                 if new_arg_supported
                 else await self._arun(*tool_args, **tool_kwargs)
             )
@@ -428,11 +489,15 @@ class ChildTool(BaseTool):
                 observation = self.handle_tool_error(e)
             else:
                 raise ValueError(
-                    "Got unexpected type of `handle_tool_error`. Expected bool, str "
-                    f"or callable. Received: {self.handle_tool_error}"
+                    "Got unexpected type of `handle_tool_error`."
+                    " Expected bool, str or callable. Received:"
+                    f" {self.handle_tool_error}"
                 )
             await run_manager.on_tool_end(
-                str(observation), color="red", name=self.name, **kwargs
+                str(observation),
+                color="red",
+                name=self.name,
+                **kwargs,
             )
             return observation
         except (Exception, KeyboardInterrupt) as e:
@@ -440,11 +505,16 @@ class ChildTool(BaseTool):
             raise e
         else:
             await run_manager.on_tool_end(
-                str(observation), color=color, name=self.name, **kwargs
+                str(observation),
+                color=color,
+                name=self.name,
+                **kwargs,
             )
             return observation
 
-    def __call__(self, tool_input: str, callbacks: Callbacks = None) -> str:
+    def __call__(
+        self, tool_input: str, callbacks: Callbacks = None
+    ) -> str:
         """Make tool callable."""
         return self.run(tool_input, callbacks=callbacks)
 
@@ -484,14 +554,17 @@ class Tool(BaseTool):
         # assume it takes a single string input.
         return {"tool_input": {"type": "string"}}
 
-    def _to_args_and_kwargs(self, tool_input: Union[str, Dict]) -> Tuple[Tuple, Dict]:
+    def _to_args_and_kwargs(
+        self, tool_input: Union[str, Dict]
+    ) -> Tuple[Tuple, Dict]:
         """Convert tool input to pydantic model."""
         args, kwargs = super()._to_args_and_kwargs(tool_input)
         # For backwards compatibility. The tool must be run with a single input
         all_args = list(args) + list(kwargs.values())
         if len(all_args) != 1:
             raise ToolException(
-                f"Too many arguments to single-input tool {self.name}. Args: {all_args}"
+                "Too many arguments to single-input tool"
+                f" {self.name}. Args: {all_args}"
             )
         return tuple(all_args), {}
 
@@ -503,11 +576,17 @@ class Tool(BaseTool):
     ) -> Any:
         """Use the tool."""
         if self.func:
-            new_argument_supported = signature(self.func).parameters.get("callbacks")
+            new_argument_supported = signature(
+                self.func
+            ).parameters.get("callbacks")
             return (
                 self.func(
                     *args,
-                    callbacks=run_manager.get_child() if run_manager else None,
+                    callbacks=(
+                        run_manager.get_child()
+                        if run_manager
+                        else None
+                    ),
                     **kwargs,
                 )
                 if new_argument_supported
@@ -523,13 +602,17 @@ class Tool(BaseTool):
     ) -> Any:
         """Use the tool asynchronously."""
         if self.coroutine:
-            new_argument_supported = signature(self.coroutine).parameters.get(
-                "callbacks"
-            )
+            new_argument_supported = signature(
+                self.coroutine
+            ).parameters.get("callbacks")
             return (
                 await self.coroutine(
                     *args,
-                    callbacks=run_manager.get_child() if run_manager else None,
+                    callbacks=(
+                        run_manager.get_child()
+                        if run_manager
+                        else None
+                    ),
                     **kwargs,
                 )
                 if new_argument_supported
@@ -537,12 +620,18 @@ class Tool(BaseTool):
             )
         else:
             return await asyncio.get_running_loop().run_in_executor(
-                None, partial(self._run, run_manager=run_manager, **kwargs), *args
+                None,
+                partial(self._run, run_manager=run_manager, **kwargs),
+                *args,
             )
 
     # TODO: this is for backwards compatibility, remove in future
     def __init__(
-        self, name: str, func: Optional[Callable], description: str, **kwargs: Any
+        self,
+        name: str,
+        func: Optional[Callable],
+        description: str,
+        **kwargs: Any,
     ) -> None:
         """Initialize tool."""
         super(Tool, self).__init__(
@@ -564,7 +653,9 @@ class Tool(BaseTool):
     ) -> Tool:
         """Initialize tool from a function."""
         if func is None and coroutine is None:
-            raise ValueError("Function and/or coroutine must be provided")
+            raise ValueError(
+                "Function and/or coroutine must be provided"
+            )
         return cls(
             name=name,
             func=func,
@@ -580,7 +671,9 @@ class StructuredTool(BaseTool):
     """Tool that can operate on any number of inputs."""
 
     description: str = ""
-    args_schema: Type[BaseModel] = Field(..., description="The tool schema.")
+    args_schema: Type[BaseModel] = Field(
+        ..., description="The tool schema."
+    )
     """The input arguments' schema."""
     func: Optional[Callable[..., Any]]
     """The function to run when the tool is called."""
@@ -617,11 +710,17 @@ class StructuredTool(BaseTool):
     ) -> Any:
         """Use the tool."""
         if self.func:
-            new_argument_supported = signature(self.func).parameters.get("callbacks")
+            new_argument_supported = signature(
+                self.func
+            ).parameters.get("callbacks")
             return (
                 self.func(
                     *args,
-                    callbacks=run_manager.get_child() if run_manager else None,
+                    callbacks=(
+                        run_manager.get_child()
+                        if run_manager
+                        else None
+                    ),
                     **kwargs,
                 )
                 if new_argument_supported
@@ -637,13 +736,17 @@ class StructuredTool(BaseTool):
     ) -> str:
         """Use the tool asynchronously."""
         if self.coroutine:
-            new_argument_supported = signature(self.coroutine).parameters.get(
-                "callbacks"
-            )
+            new_argument_supported = signature(
+                self.coroutine
+            ).parameters.get("callbacks")
             return (
                 await self.coroutine(
                     *args,
-                    callbacks=run_manager.get_child() if run_manager else None,
+                    callbacks=(
+                        run_manager.get_child()
+                        if run_manager
+                        else None
+                    ),
                     **kwargs,
                 )
                 if new_argument_supported
@@ -700,12 +803,15 @@ class StructuredTool(BaseTool):
         elif coroutine is not None:
             source_function = coroutine
         else:
-            raise ValueError("Function and/or coroutine must be provided")
+            raise ValueError(
+                "Function and/or coroutine must be provided"
+            )
         name = name or source_function.__name__
         description = description or source_function.__doc__
         if description is None:
             raise ValueError(
-                "Function must have a docstring if description not provided."
+                "Function must have a docstring if description not"
+                " provided."
             )
 
         # Description example:
@@ -714,7 +820,9 @@ class StructuredTool(BaseTool):
         description = f"{name}{sig} - {description.strip()}"
         _args_schema = args_schema
         if _args_schema is None and infer_schema:
-            _args_schema = create_schema_from_function(f"{name}Schema", source_function)
+            _args_schema = create_schema_from_function(
+                f"{name}Schema", source_function
+            )
         return cls(
             name=name,
             func=func,
@@ -762,26 +870,41 @@ def tool(
     """
 
     def _make_with_name(tool_name: str) -> Callable:
-        def _make_tool(dec_func: Union[Callable, Runnable]) -> BaseTool:
+        def _make_tool(
+            dec_func: Union[Callable, Runnable]
+        ) -> BaseTool:
             if isinstance(dec_func, Runnable):
                 runnable = dec_func
 
-                if runnable.input_schema.schema().get("type") != "object":
-                    raise ValueError("Runnable must have an object schema.")
+                if (
+                    runnable.input_schema.schema().get("type")
+                    != "object"
+                ):
+                    raise ValueError(
+                        "Runnable must have an object schema."
+                    )
 
                 async def ainvoke_wrapper(
-                    callbacks: Optional[Callbacks] = None, **kwargs: Any
+                    callbacks: Optional[Callbacks] = None,
+                    **kwargs: Any,
                 ) -> Any:
-                    return await runnable.ainvoke(kwargs, {"callbacks": callbacks})
+                    return await runnable.ainvoke(
+                        kwargs, {"callbacks": callbacks}
+                    )
 
                 def invoke_wrapper(
-                    callbacks: Optional[Callbacks] = None, **kwargs: Any
+                    callbacks: Optional[Callbacks] = None,
+                    **kwargs: Any,
                 ) -> Any:
-                    return runnable.invoke(kwargs, {"callbacks": callbacks})
+                    return runnable.invoke(
+                        kwargs, {"callbacks": callbacks}
+                    )
 
                 coroutine = ainvoke_wrapper
                 func = invoke_wrapper
-                schema: Optional[Type[BaseModel]] = runnable.input_schema
+                schema: Optional[Type[BaseModel]] = (
+                    runnable.input_schema
+                )
                 description = repr(runnable)
             elif inspect.iscoroutinefunction(dec_func):
                 coroutine = dec_func
@@ -808,8 +931,8 @@ def tool(
             # a simple string->string function
             if func.__doc__ is None:
                 raise ValueError(
-                    "Function must have a docstring if "
-                    "description not provided and infer_schema is False."
+                    "Function must have a docstring if description"
+                    " not provided and infer_schema is False."
                 )
             return Tool(
                 name=tool_name,
@@ -821,7 +944,11 @@ def tool(
 
         return _make_tool
 
-    if len(args) == 2 and isinstance(args[0], str) and isinstance(args[1], Runnable):
+    if (
+        len(args) == 2
+        and isinstance(args[0], str)
+        and isinstance(args[1], Runnable)
+    ):
         return _make_with_name(args[0])(args[1])
     elif len(args) == 1 and isinstance(args[0], str):
         # if the argument is a string, then we use the string as the tool name
diff --git a/swarms/tools/tool_func_doc_scraper.py b/swarms/tools/tool_func_doc_scraper.py
new file mode 100644
index 00000000..d233bfae
--- /dev/null
+++ b/swarms/tools/tool_func_doc_scraper.py
@@ -0,0 +1,45 @@
+import inspect
+from typing import Callable
+from termcolor import colored
+
+
+def scrape_tool_func_docs(fn: Callable) -> str:
+    """
+    Scrape the docstrings and parameters of a function decorated with `tool` and return a formatted string.
+
+    Args:
+        fn (Callable): The function to scrape.
+
+    Returns:
+        str: A string containing the function's name, documentation string, and a list of its parameters. Each parameter is represented as a line containing the parameter's name, default value, and annotation.
+    """
+    try:
+        # If the function is a tool, get the original function
+        if hasattr(fn, "func"):
+            fn = fn.func
+
+        signature = inspect.signature(fn)
+        parameters = []
+        for name, param in signature.parameters.items():
+            parameters.append(
+                f"Name: {name}, Type:"
+                f" {param.default if param.default is not param.empty else 'None'},"
+                " Annotation:"
+                f" {param.annotation if param.annotation is not param.empty else 'None'}"
+            )
+        parameters_str = "\n".join(parameters)
+        return (
+            f"Function: {fn.__name__}\nDocstring:"
+            f" {inspect.getdoc(fn)}\nParameters:\n{parameters_str}"
+        )
+    except Exception as error:
+        print(
+            colored(
+                (
+                    f"Error scraping tool function docs {error} try"
+                    " optimizing your inputs with different"
+                    " variables and attempt once more."
+                ),
+                "red",
+            )
+        )
diff --git a/swarms/tools/tool_registry.py b/swarms/tools/tool_registry.py
deleted file mode 100644
index 5aa544e9..00000000
--- a/swarms/tools/tool_registry.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from swarms.tools.tool import tool
-from typing import Dict, Callable, Any, List
-
-ToolBuilder = Callable[[Any], tool]
-FuncToolBuilder = Callable[[], ToolBuilder]
-
-
-class ToolsRegistry:
-    def __init__(self) -> None:
-        self.tools: Dict[str, FuncToolBuilder] = {}
-
-    def register(self, tool_name: str, tool: FuncToolBuilder):
-        print(f"will register {tool_name}")
-        self.tools[tool_name] = tool
-
-    def build(self, tool_name, config):
-        ret = self.tools[tool_name]()(config)
-        if isinstance(ret, tool):
-            return ret
-        raise ValueError(
-            "Tool builder {} did not return a Tool instance".format(tool_name)
-        )
-
-    def list_tools(self) -> List[str]:
-        return list(self.tools.keys())
-
-
-tools_registry = ToolsRegistry()
-
-
-def register(tool_name):
-    def decorator(tool: FuncToolBuilder):
-        tools_registry.register(tool_name, tool)
-        return tool
-
-    return decorator
-
-
-def build_tool(tool_name: str, config: Any) -> tool:
-    print(f"will build {tool_name}")
-    return tools_registry.build(tool_name, config)
-
-
-def list_tools() -> List[str]:
-    return tools_registry.list_tools()
diff --git a/swarms/tools/tool_utils.py b/swarms/tools/tool_utils.py
new file mode 100644
index 00000000..c189c9f5
--- /dev/null
+++ b/swarms/tools/tool_utils.py
@@ -0,0 +1,48 @@
+import re
+import json
+
+
+def extract_tool_commands(self, text: str):
+    """
+    Extract the tool commands from the text
+
+    Example:
+    ```json
+    {
+        "tool": "tool_name",
+        "params": {
+            "tool1": "inputs",
+            "param2": "value2"
+        }
+    }
+    ```
+
+    """
+    # Regex to find JSON like strings
+    pattern = r"```json(.+?)```"
+    matches = re.findall(pattern, text, re.DOTALL)
+    json_commands = []
+    for match in matches:
+        try:
+            json_commands = json.loads(match)
+            json_commands.append(json_commands)
+        except Exception as error:
+            print(f"Error parsing JSON command: {error}")
+
+
+def parse_and_execute_tools(response: str):
+    """Parse and execute the tools"""
+    json_commands = extract_tool_commands(response)
+    for command in json_commands:
+        tool_name = command.get("tool")
+        params = command.get("parmas", {})
+        execute_tools(tool_name, params)
+
+
+def execute_tools(self, tool_name, params):
+    """Execute the tool with the provided params"""
+    tool = self.tool_find_by_name(tool_name)
+    if tool:
+        # Execute the tool with the provided parameters
+        tool_result = tool.run(**params)
+        print(tool_result)
diff --git a/swarms/utils/__init__.py b/swarms/utils/__init__.py
index d5ce3583..8c935f26 100644
--- a/swarms/utils/__init__.py
+++ b/swarms/utils/__init__.py
@@ -1,12 +1,12 @@
-from swarms.utils.display_markdown import display_markdown_message
-from swarms.utils.futures import execute_futures_dict
+from swarms.utils.markdown_message import display_markdown_message
 from swarms.utils.code_interpreter import SubprocessCodeInterpreter
-from swarms.utils.parse_code import extract_code_in_backticks_in_string
+from swarms.utils.parse_code import (
+    extract_code_in_backticks_in_string,
+)
 from swarms.utils.pdf_to_text import pdf_to_text
 
 __all__ = [
     "display_markdown_message",
-    "execute_futures_dict",
     "SubprocessCodeInterpreter",
     "extract_code_in_backticks_in_string",
     "pdf_to_text",
diff --git a/swarms/utils/apa.py b/swarms/utils/apa.py
index 94c6f158..f2e1bb38 100644
--- a/swarms/utils/apa.py
+++ b/swarms/utils/apa.py
@@ -102,7 +102,9 @@ class Action:
     tool_name: str = ""
     tool_input: dict = field(default_factory=lambda: {})
 
-    tool_output_status: ToolCallStatus = ToolCallStatus.ToolCallSuccess
+    tool_output_status: ToolCallStatus = (
+        ToolCallStatus.ToolCallSuccess
+    )
     tool_output: str = ""
 
     def to_json(self):
@@ -124,7 +126,9 @@ class Action:
 @dataclass
 class userQuery:
     task: str
-    additional_information: List[str] = field(default_factory=lambda: [])
+    additional_information: List[str] = field(
+        default_factory=lambda: []
+    )
     refine_prompt: str = field(default_factory=lambda: "")
 
     def print_self(self):
@@ -144,7 +148,9 @@ class Singleton(abc.ABCMeta, type):
     def __call__(cls, *args, **kwargs):
         """Call method for the singleton metaclass."""
         if cls not in cls._instances:
-            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
+            cls._instances[cls] = super(Singleton, cls).__call__(
+                *args, **kwargs
+            )
         return cls._instances[cls]
 
 
diff --git a/swarms/utils/code_interpreter.py b/swarms/utils/code_interpreter.py
index 86059a83..98fbab70 100644
--- a/swarms/utils/code_interpreter.py
+++ b/swarms/utils/code_interpreter.py
@@ -116,14 +116,24 @@ class SubprocessCodeInterpreter(BaseCodeInterpreter):
                     # Most of the time it doesn't matter, but we should figure out why it happens frequently with:
                     # applescript
                     yield {"output": traceback.format_exc()}
-                    yield {"output": f"Retrying... ({retry_count}/{max_retries})"}
+                    yield {
+                        "output": (
+                            "Retrying..."
+                            f" ({retry_count}/{max_retries})"
+                        )
+                    }
                     yield {"output": "Restarting process."}
 
                 self.start_process()
 
                 retry_count += 1
                 if retry_count > max_retries:
-                    yield {"output": "Maximum retries reached. Could not execute code."}
+                    yield {
+                        "output": (
+                            "Maximum retries reached. Could not"
+                            " execute code."
+                        )
+                    }
                     return
 
         while True:
@@ -132,7 +142,9 @@ class SubprocessCodeInterpreter(BaseCodeInterpreter):
             else:
                 time.sleep(0.1)
             try:
-                output = self.output_queue.get(timeout=0.3)  # Waits for 0.3 seconds
+                output = self.output_queue.get(
+                    timeout=0.3
+                )  # Waits for 0.3 seconds
                 yield output
             except queue.Empty:
                 if self.done.is_set():
diff --git a/swarms/utils/decorators.py b/swarms/utils/decorators.py
index 8a5a5d56..e4c11574 100644
--- a/swarms/utils/decorators.py
+++ b/swarms/utils/decorators.py
@@ -31,7 +31,10 @@ def timing_decorator(func):
         start_time = time.time()
         result = func(*args, **kwargs)
         end_time = time.time()
-        logging.info(f"{func.__name__} executed in {end_time - start_time} seconds")
+        logging.info(
+            f"{func.__name__} executed in"
+            f" {end_time - start_time} seconds"
+        )
         return result
 
     return wrapper
@@ -46,7 +49,8 @@ def retry_decorator(max_retries=5):
                     return func(*args, **kwargs)
                 except Exception as error:
                     logging.error(
-                        f" Error in {func.__name__}: {str(error)} Retrying ...."
+                        f" Error in {func.__name__}:"
+                        f" {str(error)} Retrying ...."
                     )
             return func(*args, **kwargs)
 
@@ -79,7 +83,10 @@ def synchronized_decorator(func):
 def deprecated_decorator(func):
     @functools.wraps(func)
     def wrapper(*args, **kwargs):
-        warnings.warn(f"{func.__name__} is deprecated", category=DeprecationWarning)
+        warnings.warn(
+            f"{func.__name__} is deprecated",
+            category=DeprecationWarning,
+        )
         return func(*args, **kwargs)
 
     return wrapper
diff --git a/swarms/utils/disable_logging.py b/swarms/utils/disable_logging.py
new file mode 100644
index 00000000..3b6884d2
--- /dev/null
+++ b/swarms/utils/disable_logging.py
@@ -0,0 +1,36 @@
+import logging
+import os
+import warnings
+import sys
+
+
+def disable_logging():
+    log_file = open("errors.txt", "w")
+    sys.stderr = log_file
+
+    warnings.filterwarnings("ignore", category=UserWarning)
+
+    # disable tensorflow warnings
+    os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
+
+    # Set the logging level for the entire module
+    logging.basicConfig(level=logging.WARNING)
+
+    try:
+        log = logging.getLogger("pytorch")
+        log.propagate = False
+        log.setLevel(logging.ERROR)
+    except Exception as error:
+        print(f"Pytorch logging not disabled: {error}")
+
+    for logger_name in [
+        "tensorflow",
+        "h5py",
+        "numexpr",
+        "git",
+        "wandb.docker.auth",
+    ]:
+        logger = logging.getLogger(logger_name)
+        logger.setLevel(
+            logging.WARNING
+        )  # Supress DEBUG and info logs
diff --git a/swarms/utils/execute_futures.py b/swarms/utils/execute_futures.py
new file mode 100644
index 00000000..bc2d47ef
--- /dev/null
+++ b/swarms/utils/execute_futures.py
@@ -0,0 +1,42 @@
+from concurrent import futures
+from concurrent.futures import Future
+from typing import TypeVar, Dict
+
+T = TypeVar("T")
+
+
+def execute_futures_dict(
+    fs_dict: Dict[str, Future[T]]
+) -> Dict[str, T]:
+    """Execute a dictionary of futures and return the results.
+
+    Args:
+        fs_dict (dict[str, futures.Future[T]]): _description_
+
+    Returns:
+        dict[str, T]: _description_
+
+    Example:
+    >>> import concurrent.futures
+    >>> import time
+    >>> import random
+    >>> import swarms.utils.futures
+    >>> def f(x):
+    ...     time.sleep(random.random())
+    ...     return x
+    >>> with concurrent.futures.ThreadPoolExecutor() as executor:
+    ...     fs_dict = {
+    ...         str(i): executor.submit(f, i)
+    ...         for i in range(10)
+    ...     }
+    ...     print(swarms.utils.futures.execute_futures_dict(fs_dict))
+    {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
+
+    """
+    futures.wait(
+        fs_dict.values(),
+        timeout=None,
+        return_when=futures.ALL_COMPLETED,
+    )
+
+    return {key: future.result() for key, future in fs_dict.items()}
diff --git a/swarms/utils/futures.py b/swarms/utils/futures.py
deleted file mode 100644
index 55a4e5d5..00000000
--- a/swarms/utils/futures.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from concurrent import futures
-from typing import TypeVar
-
-T = TypeVar("T")
-
-
-def execute_futures_dict(fs_dict: dict[str, futures.Future[T]]) -> dict[str, T]:
-    futures.wait(fs_dict.values(), timeout=None, return_when=futures.ALL_COMPLETED)
-
-    return {key: future.result() for key, future in fs_dict.items()}
diff --git a/swarms/utils/loggers.py b/swarms/utils/loggers.py
index da822d1a..a0dec94d 100644
--- a/swarms/utils/loggers.py
+++ b/swarms/utils/loggers.py
@@ -14,7 +14,9 @@ from swarms.utils.apa import Action, ToolCallStatus
 
 # from autogpt.speech import say_text
 class JsonFileHandler(logging.FileHandler):
-    def __init__(self, filename, mode="a", encoding=None, delay=False):
+    def __init__(
+        self, filename, mode="a", encoding=None, delay=False
+    ):
         """
         Initializes a new instance of the class with the specified file name, mode, encoding, and delay settings.
 
@@ -84,7 +86,9 @@ class Logger:
         log_file = "activity.log"
         error_file = "error.log"
 
-        console_formatter = AutoGptFormatter("%(title_color)s %(message)s")
+        console_formatter = AutoGptFormatter(
+            "%(title_color)s %(message)s"
+        )
 
         # Create a handler for console which simulate typing
         self.typing_console_handler = TypingConsoleHandler()
@@ -113,7 +117,8 @@ class Logger:
         )
         error_handler.setLevel(logging.ERROR)
         error_formatter = AutoGptFormatter(
-            "%(asctime)s %(levelname)s %(module)s:%(funcName)s:%(lineno)d %(title)s"
+            "%(asctime)s %(levelname)s"
+            " %(module)s:%(funcName)s:%(lineno)d %(title)s"
             " %(message_no_color)s"
         )
         error_handler.setFormatter(error_formatter)
@@ -140,7 +145,12 @@ class Logger:
         self.chat_plugins = []
 
     def typewriter_log(
-        self, title="", title_color="", content="", speak_text=False, level=logging.INFO
+        self,
+        title="",
+        title_color="",
+        content="",
+        speak_text=False,
+        level=logging.INFO,
     ):
         """
         Logs a message to the typewriter.
@@ -165,7 +175,9 @@ class Logger:
             content = ""
 
         self.typing_logger.log(
-            level, content, extra={"title": title, "color": title_color}
+            level,
+            content,
+            extra={"title": title, "color": title_color},
         )
 
     def debug(
@@ -255,7 +267,9 @@ class Logger:
             if isinstance(message, list):
                 message = " ".join(message)
         self.logger.log(
-            level, message, extra={"title": str(title), "color": str(title_color)}
+            level,
+            message,
+            extra={"title": str(title), "color": str(title_color)},
         )
 
     def set_level(self, level):
@@ -284,12 +298,15 @@ class Logger:
         if not additionalText:
             additionalText = (
                 "Please ensure you've setup and configured everything"
-                " correctly. Read https://github.com/Torantulino/Auto-GPT#readme to "
-                "double check. You can also create a github issue or join the discord"
-                " and ask there!"
+                " correctly. Read"
+                " https://github.com/Torantulino/Auto-GPT#readme to"
+                " double check. You can also create a github issue or"
+                " join the discord and ask there!"
             )
 
-        self.typewriter_log("DOUBLE CHECK CONFIGURATION", Fore.YELLOW, additionalText)
+        self.typewriter_log(
+            "DOUBLE CHECK CONFIGURATION", Fore.YELLOW, additionalText
+        )
 
     def log_json(self, data: Any, file_name: str) -> None:
         """
@@ -358,16 +375,24 @@ class TypingConsoleHandler(logging.StreamHandler):
             transfer_enter = "<ENTER>"
             msg_transfered = str(msg).replace("\n", transfer_enter)
             transfer_space = "<4SPACE>"
-            msg_transfered = str(msg_transfered).replace("    ", transfer_space)
+            msg_transfered = str(msg_transfered).replace(
+                "    ", transfer_space
+            )
             words = msg_transfered.split()
-            words = [word.replace(transfer_enter, "\n") for word in words]
-            words = [word.replace(transfer_space, "    ") for word in words]
+            words = [
+                word.replace(transfer_enter, "\n") for word in words
+            ]
+            words = [
+                word.replace(transfer_space, "    ") for word in words
+            ]
 
             for i, word in enumerate(words):
                 print(word, end="", flush=True)
                 if i < len(words) - 1:
                     print(" ", end="", flush=True)
-                typing_speed = random.uniform(min_typing_speed, max_typing_speed)
+                typing_speed = random.uniform(
+                    min_typing_speed, max_typing_speed
+                )
                 time.sleep(typing_speed)
                 # type faster after each word
                 min_typing_speed = min_typing_speed * 0.95
@@ -425,7 +450,9 @@ class AutoGptFormatter(logging.Formatter):
         record.title = getattr(record, "title", "")
 
         if hasattr(record, "msg"):
-            record.message_no_color = remove_color_codes(getattr(record, "msg"))
+            record.message_no_color = remove_color_codes(
+                getattr(record, "msg")
+            )
         else:
             record.message_no_color = ""
         return super().format(record)
@@ -459,8 +486,12 @@ def print_action_base(action: Action):
         None
     """
     if action.content != "":
-        logger.typewriter_log(f"content:", Fore.YELLOW, f"{action.content}")
-    logger.typewriter_log(f"Thought:", Fore.YELLOW, f"{action.thought}")
+        logger.typewriter_log(
+            f"content:", Fore.YELLOW, f"{action.content}"
+        )
+    logger.typewriter_log(
+        f"Thought:", Fore.YELLOW, f"{action.thought}"
+    )
     if len(action.plan) > 0:
         logger.typewriter_log(
             f"Plan:",
@@ -469,7 +500,9 @@ def print_action_base(action: Action):
         for line in action.plan:
             line = line.lstrip("- ")
             logger.typewriter_log("- ", Fore.GREEN, line.strip())
-    logger.typewriter_log(f"Criticism:", Fore.YELLOW, f"{action.criticism}")
+    logger.typewriter_log(
+        f"Criticism:", Fore.YELLOW, f"{action.criticism}"
+    )
 
 
 def print_action_tool(action: Action):
@@ -483,15 +516,21 @@ def print_action_tool(action: Action):
         None
     """
     logger.typewriter_log(f"Tool:", Fore.BLUE, f"{action.tool_name}")
-    logger.typewriter_log(f"Tool Input:", Fore.BLUE, f"{action.tool_input}")
+    logger.typewriter_log(
+        f"Tool Input:", Fore.BLUE, f"{action.tool_input}"
+    )
 
-    output = action.tool_output if action.tool_output != "" else "None"
+    output = (
+        action.tool_output if action.tool_output != "" else "None"
+    )
     logger.typewriter_log(f"Tool Output:", Fore.BLUE, f"{output}")
 
     color = Fore.RED
     if action.tool_output_status == ToolCallStatus.ToolCallSuccess:
         color = Fore.GREEN
-    elif action.tool_output_status == ToolCallStatus.InputCannotParsed:
+    elif (
+        action.tool_output_status == ToolCallStatus.InputCannotParsed
+    ):
         color = Fore.YELLOW
 
     logger.typewriter_log(
diff --git a/swarms/utils/main.py b/swarms/utils/main.py
index a6c4fc34..c9c0f380 100644
--- a/swarms/utils/main.py
+++ b/swarms/utils/main.py
@@ -36,7 +36,9 @@ def cut_dialogue_history(history_memory, keep_last_n_words=500):
         paragraphs = history_memory.split("\n")
         last_n_tokens = n_tokens
         while last_n_tokens >= keep_last_n_words:
-            last_n_tokens = last_n_tokens - len(paragraphs[0].split(" "))
+            last_n_tokens = last_n_tokens - len(
+                paragraphs[0].split(" ")
+            )
             paragraphs = paragraphs[1:]
         return "\n" + "\n".join(paragraphs)
 
@@ -51,14 +53,20 @@ def get_new_image_name(org_img_name, func_name="update"):
         most_org_file_name = name_split[0]
         recent_prev_file_name = name_split[0]
         new_file_name = "{}_{}_{}_{}.png".format(
-            this_new_uuid, func_name, recent_prev_file_name, most_org_file_name
+            this_new_uuid,
+            func_name,
+            recent_prev_file_name,
+            most_org_file_name,
         )
     else:
         assert len(name_split) == 4
         most_org_file_name = name_split[3]
         recent_prev_file_name = name_split[0]
         new_file_name = "{}_{}_{}_{}.png".format(
-            this_new_uuid, func_name, recent_prev_file_name, most_org_file_name
+            this_new_uuid,
+            func_name,
+            recent_prev_file_name,
+            most_org_file_name,
         )
     return os.path.join(head, new_file_name)
 
@@ -73,14 +81,20 @@ def get_new_dataframe_name(org_img_name, func_name="update"):
         most_org_file_name = name_split[0]
         recent_prev_file_name = name_split[0]
         new_file_name = "{}_{}_{}_{}.csv".format(
-            this_new_uuid, func_name, recent_prev_file_name, most_org_file_name
+            this_new_uuid,
+            func_name,
+            recent_prev_file_name,
+            most_org_file_name,
         )
     else:
         assert len(name_split) == 4
         most_org_file_name = name_split[3]
         recent_prev_file_name = name_split[0]
         new_file_name = "{}_{}_{}_{}.csv".format(
-            this_new_uuid, func_name, recent_prev_file_name, most_org_file_name
+            this_new_uuid,
+            func_name,
+            recent_prev_file_name,
+            most_org_file_name,
         )
     return os.path.join(head, new_file_name)
 
@@ -187,7 +201,11 @@ class ANSI:
         self.args = []
 
     def join(self) -> str:
-        return ANSI.ESCAPE + ";".join([str(a) for a in self.args]) + ANSI.CLOSE
+        return (
+            ANSI.ESCAPE
+            + ";".join([str(a) for a in self.args])
+            + ANSI.CLOSE
+        )
 
     def wrap(self, text: str) -> str:
         return self.join() + text + ANSI(Style.reset()).join()
@@ -201,7 +219,9 @@ def dim_multiline(message: str) -> str:
     lines = message.split("\n")
     if len(lines) <= 1:
         return lines[0]
-    return lines[0] + ANSI("\n... ".join([""] + lines[1:])).to(Color.black().bright())
+    return lines[0] + ANSI("\n... ".join([""] + lines[1:])).to(
+        Color.black().bright()
+    )
 
 
 # +=============================> ANSI Ending
@@ -227,7 +247,9 @@ class AbstractUploader(ABC):
 
 
 class S3Uploader(AbstractUploader):
-    def __init__(self, accessKey: str, secretKey: str, region: str, bucket: str):
+    def __init__(
+        self, accessKey: str, secretKey: str, region: str, bucket: str
+    ):
         self.accessKey = accessKey
         self.secretKey = secretKey
         self.region = region
@@ -334,11 +356,15 @@ class BaseHandler:
 
 
 class FileHandler:
-    def __init__(self, handlers: Dict[FileType, BaseHandler], path: Path):
+    def __init__(
+        self, handlers: Dict[FileType, BaseHandler], path: Path
+    ):
         self.handlers = handlers
         self.path = path
 
-    def register(self, filetype: FileType, handler: BaseHandler) -> "FileHandler":
+    def register(
+        self, filetype: FileType, handler: BaseHandler
+    ) -> "FileHandler":
         self.handlers[filetype] = handler
         return self
 
@@ -356,11 +382,20 @@ class FileHandler:
 
     def handle(self, url: str) -> str:
         try:
-            if url.startswith(os.environ.get("SERVER", "http://localhost:8000")):
+            if url.startswith(
+                os.environ.get("SERVER", "http://localhost:8000")
+            ):
                 local_filepath = url[
-                    len(os.environ.get("SERVER", "http://localhost:8000")) + 1 :
+                    len(
+                        os.environ.get(
+                            "SERVER", "http://localhost:8000"
+                        )
+                    )
+                    + 1 :
                 ]
-                local_filename = Path("file") / local_filepath.split("/")[-1]
+                local_filename = (
+                    Path("file") / local_filepath.split("/")[-1]
+                )
                 src = self.path / local_filepath
                 dst = (
                     self.path
@@ -375,11 +410,14 @@ class FileHandler:
             if handler is None:
                 if FileType.from_url(url) == FileType.IMAGE:
                     raise Exception(
-                        f"No handler for {FileType.from_url(url)}. "
-                        "Please set USE_GPU to True in env/settings.py"
+                        f"No handler for {FileType.from_url(url)}."
+                        " Please set USE_GPU to True in"
+                        " env/settings.py"
                     )
                 else:
-                    raise Exception(f"No handler for {FileType.from_url(url)}")
+                    raise Exception(
+                        f"No handler for {FileType.from_url(url)}"
+                    )
             return handler.handle(local_filename)
         except Exception as e:
             raise e
@@ -387,4 +425,4 @@ class FileHandler:
 
 # =>  base end
 
-# ===========================>
\ No newline at end of file
+# ===========================>
diff --git a/swarms/utils/parse_code.py b/swarms/utils/parse_code.py
index a2f346ea..2e0fa438 100644
--- a/swarms/utils/parse_code.py
+++ b/swarms/utils/parse_code.py
@@ -1,11 +1,31 @@
 import re
 
+# def extract_code_in_backticks_in_string(s: str) -> str:
+# """
+# Extracts code blocks from a markdown string.
 
-def extract_code_in_backticks_in_string(message: str) -> str:
+# Args:
+#     s (str): The markdown string to extract code from.
+
+# Returns:
+#     list: A list of tuples. Each tuple contains the language of the code block (if specified) and the code itself.
+# """
+# pattern = r"```([\w\+\#\-\.\s]*)\n(.*?)```"
+# matches = re.findall(pattern, s, re.DOTALL)
+# out =  [(match[0], match[1].strip()) for match in matches]
+# print(out)
+
+
+def extract_code_in_backticks_in_string(s: str) -> str:
     """
-    To extract code from a string in markdown and return a string
+    Extracts code blocks from a markdown string.
+
+    Args:
+        s (str): The markdown string to extract code from.
 
+    Returns:
+        str: A string containing all the code blocks.
     """
-    pattern = r"`` ``(.*?)`` "  # Non-greedy match between six backticks
-    match = re.search(pattern, message, re.DOTALL)  # re.DOTALL to match newline chars
-    return match.group(1).strip() if match else None
+    pattern = r"```([\w\+\#\-\.\s]*)(.*?)```"
+    matches = re.findall(pattern, s, re.DOTALL)
+    return "\n".join(match[1].strip() for match in matches)
diff --git a/swarms/utils/pdf_to_text.py b/swarms/utils/pdf_to_text.py
index b8778841..35309dd3 100644
--- a/swarms/utils/pdf_to_text.py
+++ b/swarms/utils/pdf_to_text.py
@@ -4,7 +4,10 @@ import os
 try:
     import PyPDF2
 except ImportError:
-    print("PyPDF2 not installed. Please install it using: pip install PyPDF2")
+    print(
+        "PyPDF2 not installed. Please install it using: pip install"
+        " PyPDF2"
+    )
     sys.exit(1)
 
 
@@ -34,9 +37,13 @@ def pdf_to_text(pdf_path):
 
             return text
     except FileNotFoundError:
-        raise FileNotFoundError(f"The file at {pdf_path} was not found.")
+        raise FileNotFoundError(
+            f"The file at {pdf_path} was not found."
+        )
     except Exception as e:
-        raise Exception(f"An error occurred while reading the PDF file: {e}")
+        raise Exception(
+            f"An error occurred while reading the PDF file: {e}"
+        )
 
 
 # Example usage
diff --git a/swarms/utils/serializable.py b/swarms/utils/serializable.py
index 8f0e5ccf..de9444ef 100644
--- a/swarms/utils/serializable.py
+++ b/swarms/utils/serializable.py
@@ -74,7 +74,9 @@ class Serializable(BaseModel, ABC):
         super().__init__(**kwargs)
         self._lc_kwargs = kwargs
 
-    def to_json(self) -> Union[SerializedConstructor, SerializedNotImplemented]:
+    def to_json(
+        self,
+    ) -> Union[SerializedConstructor, SerializedNotImplemented]:
         if not self.lc_serializable:
             return self.to_json_not_implemented()
 
@@ -93,7 +95,10 @@ class Serializable(BaseModel, ABC):
                 break
 
             # Get a reference to self bound to each class in the MRO
-            this = cast(Serializable, self if cls is None else super(cls, self))
+            this = cast(
+                Serializable,
+                self if cls is None else super(cls, self),
+            )
 
             secrets.update(this.lc_secrets)
             lc_kwargs.update(this.lc_attributes)
@@ -101,7 +106,9 @@ class Serializable(BaseModel, ABC):
         # include all secrets, even if not specified in kwargs
         # as these secrets may be passed as an environment variable instead
         for key in secrets.keys():
-            secret_value = getattr(self, key, None) or lc_kwargs.get(key)
+            secret_value = getattr(self, key, None) or lc_kwargs.get(
+                key
+            )
             if secret_value is not None:
                 lc_kwargs.update({key: secret_value})
 
@@ -109,9 +116,11 @@ class Serializable(BaseModel, ABC):
             "lc": 1,
             "type": "constructor",
             "id": [*self.lc_namespace, self.__class__.__name__],
-            "kwargs": lc_kwargs
-            if not secrets
-            else _replace_secrets(lc_kwargs, secrets),
+            "kwargs": (
+                lc_kwargs
+                if not secrets
+                else _replace_secrets(lc_kwargs, secrets)
+            ),
         }
 
     def to_json_not_implemented(self) -> SerializedNotImplemented:
@@ -153,7 +162,10 @@ def to_json_not_implemented(obj: object) -> SerializedNotImplemented:
         if hasattr(obj, "__name__"):
             _id = [*obj.__module__.split("."), obj.__name__]
         elif hasattr(obj, "__class__"):
-            _id = [*obj.__class__.__module__.split("."), obj.__class__.__name__]
+            _id = [
+                *obj.__class__.__module__.split("."),
+                obj.__class__.__name__,
+            ]
     except Exception:
         pass
     return {
diff --git a/swarms/utils/token_count_tiktoken.py b/swarms/utils/token_count_tiktoken.py
new file mode 100644
index 00000000..f8a47b98
--- /dev/null
+++ b/swarms/utils/token_count_tiktoken.py
@@ -0,0 +1,27 @@
+import tiktoken
+
+
+def limit_tokens_from_string(
+    string: str, model: str = "gpt-4", limit: int = 500
+) -> str:
+    """Limits the number of tokens in a string
+
+    Args:
+        string (str): _description_
+        model (str): _description_
+        limit (int): _description_
+
+    Returns:
+        str: _description_
+    """
+    try:
+        encoding = tiktoken.encoding_for_model(model)
+    except Exception:
+        encoding = tiktoken.encoding_for_model(
+            "gpt2"
+        )  # Fallback for others.
+
+    encoded = encoding.encode(string)
+
+    out = encoding.decode(encoded[:limit])
+    return out
diff --git a/tests/Dockerfile b/tests/Dockerfile
index b36c8d25..f6e46515 100644
--- a/tests/Dockerfile
+++ b/tests/Dockerfile
@@ -21,7 +21,6 @@ RUN pip install poetry
 
 # Disable virtualenv creation by poetry and install dependencies
 RUN poetry config virtualenvs.create false
-RUN poetry install --no-interaction --no-ansi
 
 # Install the 'swarms' package if it's not included in the poetry.lock
 RUN pip install swarms
@@ -30,4 +29,4 @@ RUN pip install swarms
 RUN pip install pytest
 
 # Run pytest on all tests in the tests directory
-CMD find ./tests -name '*.py' -exec pytest {} +
+CMD pytest
diff --git a/tests/agents/idea_to_image.py b/tests/agents/idea_to_image.py
deleted file mode 100644
index 7aecd5c5..00000000
--- a/tests/agents/idea_to_image.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import pytest
-import os
-import shutil
-from swarms.agents.idea_to_image_agent import Idea2Image
-
-openai_key = os.getenv("OPENAI_API_KEY")
-dalle_cookie = os.getenv("BING_COOKIE")
-
-# Constants for testing
-TEST_PROMPT = "Happy fish."
-TEST_OUTPUT_FOLDER = "test_images/"
-OPENAI_API_KEY = openai_key
-DALLE_COOKIE = dalle_cookie
-
-
-@pytest.fixture(scope="module")
-def idea2image_instance():
-    # Create an instance of the Idea2Image class
-    idea2image = Idea2Image(
-        image=TEST_PROMPT,
-        openai_api_key=OPENAI_API_KEY,
-        cookie=DALLE_COOKIE,
-        output_folder=TEST_OUTPUT_FOLDER,
-    )
-    yield idea2image
-    # Clean up the test output folder after testing
-    if os.path.exists(TEST_OUTPUT_FOLDER):
-        shutil.rmtree(TEST_OUTPUT_FOLDER)
-
-
-def test_idea2image_instance(idea2image_instance):
-    # Check if the instance is created successfully
-    assert isinstance(idea2image_instance, Idea2Image)
-
-
-def test_llm_prompt(idea2image_instance):
-    # Test the llm_prompt method
-    prompt = idea2image_instance.llm_prompt()
-    assert isinstance(prompt, str)
-
-
-def test_generate_image(idea2image_instance):
-    # Test the generate_image method
-    idea2image_instance.generate_image()
-    # Check if the output folder is created
-    assert os.path.exists(TEST_OUTPUT_FOLDER)
-    # Check if files are downloaded (assuming DALLE-3 responds with URLs)
-    files = os.listdir(TEST_OUTPUT_FOLDER)
-    assert len(files) > 0
-
-
-def test_invalid_openai_api_key():
-    # Test with an invalid OpenAI API key
-    with pytest.raises(Exception) as exc_info:
-        Idea2Image(
-            image=TEST_PROMPT,
-            openai_api_key="invalid_api_key",
-            cookie=DALLE_COOKIE,
-            output_folder=TEST_OUTPUT_FOLDER,
-        )
-    assert "Failed to initialize OpenAIChat" in str(exc_info.value)
-
-
-if __name__ == "__main__":
-    pytest.main()
diff --git a/tests/agents/omni_modal.py b/tests/agents/omni_modal.py
deleted file mode 100644
index d106f66c..00000000
--- a/tests/agents/omni_modal.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import pytest
-from langchain.base_language import BaseLanguageModel
-
-from swarms.agents.omni_modal_agent import (
-    OmniModalAgent,  # Replace `your_module_name` with the appropriate module name
-)
-
-
-# Mock objects or set up fixtures for dependent classes or external methods
-@pytest.fixture
-def mock_llm():
-    # For this mock, we are assuming the BaseLanguageModel has a method named "process"
-    class MockLLM(BaseLanguageModel):
-        def process(self, input):
-            return "mock response"
-
-    return MockLLM()
-
-
-@pytest.fixture
-def omni_agent(mock_llm):
-    return OmniModalAgent(mock_llm)
-
-
-def test_omnimodalagent_initialization(omni_agent):
-    assert omni_agent.llm is not None, "LLM initialization failed"
-    assert len(omni_agent.tools) > 0, "Tools initialization failed"
-
-
-def test_omnimodalagent_run(omni_agent):
-    input_string = "Hello, how are you?"
-    response = omni_agent.run(input_string)
-    assert response is not None, "Response generation failed"
-    assert isinstance(response, str), "Response should be a string"
-
-
-def test_task_executor_initialization(omni_agent):
-    assert omni_agent.task_executor is not None, "TaskExecutor initialization failed"
diff --git a/tests/embeddings/pegasus.py b/tests/embeddings/pegasus.py
deleted file mode 100644
index e9632eae..00000000
--- a/tests/embeddings/pegasus.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import pytest
-from unittest.mock import patch
-from swarms.models.pegasus import PegasusEmbedding
-
-
-def test_init():
-    with patch("your_module.Pegasus") as MockPegasus:
-        embedder = PegasusEmbedding(modality="text")
-        MockPegasus.assert_called_once()
-        assert embedder.pegasus == MockPegasus.return_value
-
-
-def test_init_exception():
-    with patch("your_module.Pegasus", side_effect=Exception("Test exception")):
-        with pytest.raises(Exception) as e:
-            PegasusEmbedding(modality="text")
-        assert str(e.value) == "Test exception"
-
-
-def test_embed():
-    with patch("your_module.Pegasus") as MockPegasus:
-        embedder = PegasusEmbedding(modality="text")
-        embedder.embed("Hello world")
-        MockPegasus.return_value.embed.assert_called_once()
-
-
-def test_embed_exception():
-    with patch("your_module.Pegasus") as MockPegasus:
-        MockPegasus.return_value.embed.side_effect = Exception("Test exception")
-        embedder = PegasusEmbedding(modality="text")
-        with pytest.raises(Exception) as e:
-            embedder.embed("Hello world")
-        assert str(e.value) == "Test exception"
diff --git a/tests/memory/main.py b/tests/memory/main.py
deleted file mode 100644
index 851de26a..00000000
--- a/tests/memory/main.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import pytest
-from unittest.mock import Mock
-from swarms.memory.ocean import OceanDB
-
-
-@pytest.fixture
-def mock_ocean_client():
-    return Mock()
-
-
-@pytest.fixture
-def mock_collection():
-    return Mock()
-
-
-@pytest.fixture
-def ocean_db(mock_ocean_client):
-    OceanDB.client = mock_ocean_client
-    return OceanDB()
-
-
-def test_init(ocean_db, mock_ocean_client):
-    mock_ocean_client.heartbeat.return_value = "OK"
-    assert ocean_db.client.heartbeat() == "OK"
-
-
-def test_create_collection(ocean_db, mock_ocean_client, mock_collection):
-    mock_ocean_client.create_collection.return_value = mock_collection
-    collection = ocean_db.create_collection("test", "text")
-    assert collection == mock_collection
-
-
-def test_append_document(ocean_db, mock_collection):
-    document = "test_document"
-    id = "test_id"
-    ocean_db.append_document(mock_collection, document, id)
-    mock_collection.add.assert_called_once_with(documents=[document], ids=[id])
-
-
-def test_add_documents(ocean_db, mock_collection):
-    documents = ["test_document1", "test_document2"]
-    ids = ["test_id1", "test_id2"]
-    ocean_db.add_documents(mock_collection, documents, ids)
-    mock_collection.add.assert_called_once_with(documents=documents, ids=ids)
-
-
-def test_query(ocean_db, mock_collection):
-    query_texts = ["test_query"]
-    n_results = 10
-    mock_collection.query.return_value = "query_result"
-    result = ocean_db.query(mock_collection, query_texts, n_results)
-    assert result == "query_result"
diff --git a/tests/memory/oceandb.py b/tests/memory/oceandb.py
deleted file mode 100644
index 3e31afab..00000000
--- a/tests/memory/oceandb.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import pytest
-from unittest.mock import Mock, patch
-from swarms.memory.ocean import OceanDB
-
-
-def test_init():
-    with patch("oceandb.Client") as MockClient:
-        MockClient.return_value.heartbeat.return_value = "OK"
-        db = OceanDB(MockClient)
-        MockClient.assert_called_once()
-        assert db.client == MockClient
-
-
-def test_init_exception():
-    with patch("oceandb.Client") as MockClient:
-        MockClient.side_effect = Exception("Client error")
-        with pytest.raises(Exception) as e:
-            OceanDB(MockClient)
-        assert str(e.value) == "Client error"
-
-
-def test_create_collection():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        db.create_collection("test", "modality")
-        MockClient.create_collection.assert_called_once_with(
-            "test", embedding_function=Mock.ANY
-        )
-
-
-def test_create_collection_exception():
-    with patch("oceandb.Client") as MockClient:
-        MockClient.create_collection.side_effect = Exception("Create collection error")
-        db = OceanDB(MockClient)
-        with pytest.raises(Exception) as e:
-            db.create_collection("test", "modality")
-        assert str(e.value) == "Create collection error"
-
-
-def test_append_document():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        collection = Mock()
-        db.append_document(collection, "doc", "id")
-        collection.add.assert_called_once_with(documents=["doc"], ids=["id"])
-
-
-def test_append_document_exception():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        collection = Mock()
-        collection.add.side_effect = Exception("Append document error")
-        with pytest.raises(Exception) as e:
-            db.append_document(collection, "doc", "id")
-        assert str(e.value) == "Append document error"
-
-
-def test_add_documents():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        collection = Mock()
-        db.add_documents(collection, ["doc1", "doc2"], ["id1", "id2"])
-        collection.add.assert_called_once_with(
-            documents=["doc1", "doc2"], ids=["id1", "id2"]
-        )
-
-
-def test_add_documents_exception():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        collection = Mock()
-        collection.add.side_effect = Exception("Add documents error")
-        with pytest.raises(Exception) as e:
-            db.add_documents(collection, ["doc1", "doc2"], ["id1", "id2"])
-        assert str(e.value) == "Add documents error"
-
-
-def test_query():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        collection = Mock()
-        db.query(collection, ["query1", "query2"], 2)
-        collection.query.assert_called_once_with(
-            query_texts=["query1", "query2"], n_results=2
-        )
-
-
-def test_query_exception():
-    with patch("oceandb.Client") as MockClient:
-        db = OceanDB(MockClient)
-        collection = Mock()
-        collection.query.side_effect = Exception("Query error")
-        with pytest.raises(Exception) as e:
-            db.query(collection, ["query1", "query2"], 2)
-        assert str(e.value) == "Query error"
diff --git a/tests/memory/pg.py b/tests/memory/test_pg.py
similarity index 91%
rename from tests/memory/pg.py
rename to tests/memory/test_pg.py
index e7b0587d..2bddfb27 100644
--- a/tests/memory/pg.py
+++ b/tests/memory/test_pg.py
@@ -1,6 +1,6 @@
 import pytest
 from unittest.mock import patch
-from swarms.memory import PgVectorVectorStore
+from swarms.memory.pg import PgVectorVectorStore
 from dotenv import load_dotenv
 import os
 
@@ -23,7 +23,9 @@ def test_init():
 def test_init_exception():
     with pytest.raises(ValueError):
         PgVectorVectorStore(
-            connection_string="mysql://root:password@localhost:3306/test",
+            connection_string=(
+                "mysql://root:password@localhost:3306/test"
+            ),
             table_name="test",
         )
 
@@ -47,7 +49,10 @@ def test_upsert_vector():
             table_name="test",
         )
         store.upsert_vector(
-            [1.0, 2.0, 3.0], "test_id", "test_namespace", {"meta": "data"}
+            [1.0, 2.0, 3.0],
+            "test_id",
+            "test_namespace",
+            {"meta": "data"},
         )
         MockSession.assert_called()
         MockSession.return_value.merge.assert_called()
diff --git a/tests/memory/pinecone.py b/tests/memory/test_pinecone.py
similarity index 63%
rename from tests/memory/pinecone.py
rename to tests/memory/test_pinecone.py
index bd037bef..7c71503e 100644
--- a/tests/memory/pinecone.py
+++ b/tests/memory/test_pinecone.py
@@ -1,14 +1,18 @@
 import os
 from unittest.mock import patch
-from swarms.memory import PineconeVectorStore
+from swarms.memory.pinecone import PineconeVectorStore
 
 api_key = os.getenv("PINECONE_API_KEY") or ""
 
 
 def test_init():
-    with patch("pinecone.init") as MockInit, patch("pinecone.Index") as MockIndex:
+    with patch("pinecone.init") as MockInit, patch(
+        "pinecone.Index"
+    ) as MockIndex:
         store = PineconeVectorStore(
-            api_key=api_key, index_name="test_index", environment="test_env"
+            api_key=api_key,
+            index_name="test_index",
+            environment="test_env",
         )
         MockInit.assert_called_once()
         MockIndex.assert_called_once()
@@ -18,10 +22,15 @@ def test_init():
 def test_upsert_vector():
     with patch("pinecone.init"), patch("pinecone.Index") as MockIndex:
         store = PineconeVectorStore(
-            api_key=api_key, index_name="test_index", environment="test_env"
+            api_key=api_key,
+            index_name="test_index",
+            environment="test_env",
         )
         store.upsert_vector(
-            [1.0, 2.0, 3.0], "test_id", "test_namespace", {"meta": "data"}
+            [1.0, 2.0, 3.0],
+            "test_id",
+            "test_namespace",
+            {"meta": "data"},
         )
         MockIndex.return_value.upsert.assert_called()
 
@@ -29,7 +38,9 @@ def test_upsert_vector():
 def test_load_entry():
     with patch("pinecone.init"), patch("pinecone.Index") as MockIndex:
         store = PineconeVectorStore(
-            api_key=api_key, index_name="test_index", environment="test_env"
+            api_key=api_key,
+            index_name="test_index",
+            environment="test_env",
         )
         store.load_entry("test_id", "test_namespace")
         MockIndex.return_value.fetch.assert_called()
@@ -38,7 +49,9 @@ def test_load_entry():
 def test_load_entries():
     with patch("pinecone.init"), patch("pinecone.Index") as MockIndex:
         store = PineconeVectorStore(
-            api_key=api_key, index_name="test_index", environment="test_env"
+            api_key=api_key,
+            index_name="test_index",
+            environment="test_env",
         )
         store.load_entries("test_namespace")
         MockIndex.return_value.query.assert_called()
@@ -47,7 +60,9 @@ def test_load_entries():
 def test_query():
     with patch("pinecone.init"), patch("pinecone.Index") as MockIndex:
         store = PineconeVectorStore(
-            api_key=api_key, index_name="test_index", environment="test_env"
+            api_key=api_key,
+            index_name="test_index",
+            environment="test_env",
         )
         store.query("test_query", 10, "test_namespace")
         MockIndex.return_value.query.assert_called()
@@ -58,7 +73,9 @@ def test_create_index():
         "pinecone.create_index"
     ) as MockCreateIndex:
         store = PineconeVectorStore(
-            api_key=api_key, index_name="test_index", environment="test_env"
+            api_key=api_key,
+            index_name="test_index",
+            environment="test_env",
         )
         store.create_index("test_index")
         MockCreateIndex.assert_called()
diff --git a/tests/memory/test_qdrant.py b/tests/memory/test_qdrant.py
new file mode 100644
index 00000000..12a6af84
--- /dev/null
+++ b/tests/memory/test_qdrant.py
@@ -0,0 +1,53 @@
+import pytest
+from unittest.mock import Mock, patch
+
+from swarms.memory.qdrant import Qdrant
+
+
+@pytest.fixture
+def mock_qdrant_client():
+    with patch("your_module.QdrantClient") as MockQdrantClient:
+        yield MockQdrantClient()
+
+
+@pytest.fixture
+def mock_sentence_transformer():
+    with patch(
+        "sentence_transformers.SentenceTransformer"
+    ) as MockSentenceTransformer:
+        yield MockSentenceTransformer()
+
+
+@pytest.fixture
+def qdrant_client(mock_qdrant_client, mock_sentence_transformer):
+    client = Qdrant(api_key="your_api_key", host="your_host")
+    yield client
+
+
+def test_qdrant_init(qdrant_client, mock_qdrant_client):
+    assert qdrant_client.client is not None
+
+
+def test_load_embedding_model(
+    qdrant_client, mock_sentence_transformer
+):
+    qdrant_client._load_embedding_model("model_name")
+    mock_sentence_transformer.assert_called_once_with("model_name")
+
+
+def test_setup_collection(qdrant_client, mock_qdrant_client):
+    qdrant_client._setup_collection()
+    mock_qdrant_client.get_collection.assert_called_once_with(
+        qdrant_client.collection_name
+    )
+
+
+def test_add_vectors(qdrant_client, mock_qdrant_client):
+    mock_doc = Mock(page_content="Sample text")
+    qdrant_client.add_vectors([mock_doc])
+    mock_qdrant_client.upsert.assert_called_once()
+
+
+def test_search_vectors(qdrant_client, mock_qdrant_client):
+    qdrant_client.search_vectors("test query")
+    mock_qdrant_client.search.assert_called_once()
diff --git a/tests/models/bingchat.py b/tests/models/bingchat.py
deleted file mode 100644
index ce3af99d..00000000
--- a/tests/models/bingchat.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import unittest
-import json
-import os
-
-# Assuming the BingChat class is in a file named "bing_chat.py"
-from bing_chat import BingChat
-
-
-class TestBingChat(unittest.TestCase):
-    def setUp(self):
-        # Path to a mock cookies file for testing
-        self.mock_cookies_path = "./mock_cookies.json"
-        with open(self.mock_cookies_path, "w") as file:
-            json.dump({"mock_cookie": "mock_value"}, file)
-
-        self.chat = BingChat(cookies_path=self.mock_cookies_path)
-
-    def tearDown(self):
-        os.remove(self.mock_cookies_path)
-
-    def test_init(self):
-        self.assertIsInstance(self.chat, BingChat)
-        self.assertIsNotNone(self.chat.bot)
-
-    def test_call(self):
-        # Mocking the asynchronous behavior for the purpose of the test
-        self.chat.bot.ask = lambda *args, **kwargs: {"text": "Hello, Test!"}
-        response = self.chat("Test prompt")
-        self.assertEqual(response, "Hello, Test!")
-
-    def test_create_img(self):
-        # Mocking the ImageGen behavior for the purpose of the test
-        class MockImageGen:
-            def __init__(self, *args, **kwargs):
-                pass
-
-            def get_images(self, *args, **kwargs):
-                return [{"path": "mock_image.png"}]
-
-            @staticmethod
-            def save_images(*args, **kwargs):
-                pass
-
-        original_image_gen = BingChat.ImageGen
-        BingChat.ImageGen = MockImageGen
-
-        img_path = self.chat.create_img("Test prompt", auth_cookie="mock_auth_cookie")
-        self.assertEqual(img_path, "./output/mock_image.png")
-
-        BingChat.ImageGen = original_image_gen
-
-    def test_set_cookie_dir_path(self):
-        test_path = "./test_path"
-        BingChat.set_cookie_dir_path(test_path)
-        self.assertEqual(BingChat.Cookie.dir_path, test_path)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/tests/models/revgptv1.py b/tests/models/revgptv1.py
deleted file mode 100644
index 12ceeea0..00000000
--- a/tests/models/revgptv1.py
+++ /dev/null
@@ -1,83 +0,0 @@
-import unittest
-from unittest.mock import patch
-from Sswarms.models.revgptv1 import RevChatGPTModelv1
-
-
-class TestRevChatGPT(unittest.TestCase):
-    def setUp(self):
-        self.access_token = "<your_access_token>"
-        self.model = RevChatGPTModelv1(access_token=self.access_token)
-
-    def test_run(self):
-        prompt = "What is the capital of France?"
-        response = self.model.run(prompt)
-        self.assertEqual(response, "The capital of France is Paris.")
-
-    def test_run_time(self):
-        prompt = "Generate a 300 word essay about technology."
-        self.model.run(prompt)
-        self.assertLess(self.model.end_time - self.model.start_time, 60)
-
-    def test_generate_summary(self):
-        text = "This is a sample text to summarize. It has multiple sentences and details. The summary should be concise."
-        summary = self.model.generate_summary(text)
-        self.assertLess(len(summary), len(text) / 2)
-
-    def test_enable_plugin(self):
-        plugin_id = "some_plugin_id"
-        self.model.enable_plugin(plugin_id)
-        self.assertIn(plugin_id, self.model.config["plugin_ids"])
-
-    def test_list_plugins(self):
-        plugins = self.model.list_plugins()
-        self.assertGreater(len(plugins), 0)
-        self.assertIsInstance(plugins[0], dict)
-        self.assertIn("id", plugins[0])
-        self.assertIn("name", plugins[0])
-
-    def test_get_conversations(self):
-        conversations = self.model.chatbot.get_conversations()
-        self.assertIsInstance(conversations, list)
-
-    @patch("RevChatGPTModelv1.Chatbot.get_msg_history")
-    def test_get_msg_history(self, mock_get_msg_history):
-        conversation_id = "convo_id"
-        self.model.chatbot.get_msg_history(conversation_id)
-        mock_get_msg_history.assert_called_with(conversation_id)
-
-    @patch("RevChatGPTModelv1.Chatbot.share_conversation")
-    def test_share_conversation(self, mock_share_conversation):
-        self.model.chatbot.share_conversation()
-        mock_share_conversation.assert_called()
-
-    def test_gen_title(self):
-        convo_id = "123"
-        message_id = "456"
-        title = self.model.chatbot.gen_title(convo_id, message_id)
-        self.assertIsInstance(title, str)
-
-    def test_change_title(self):
-        convo_id = "123"
-        title = "New Title"
-        self.model.chatbot.change_title(convo_id, title)
-        self.assertEqual(self.model.chatbot.get_msg_history(convo_id)["title"], title)
-
-    def test_delete_conversation(self):
-        convo_id = "123"
-        self.model.chatbot.delete_conversation(convo_id)
-        with self.assertRaises(Exception):
-            self.model.chatbot.get_msg_history(convo_id)
-
-    def test_clear_conversations(self):
-        self.model.chatbot.clear_conversations()
-        conversations = self.model.chatbot.get_conversations()
-        self.assertEqual(len(conversations), 0)
-
-    def test_rollback_conversation(self):
-        original_convo_id = self.model.chatbot.conversation_id
-        self.model.chatbot.rollback_conversation(1)
-        self.assertNotEqual(original_convo_id, self.model.chatbot.conversation_id)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/tests/models/revgptv4.py b/tests/models/revgptv4.py
deleted file mode 100644
index 7a40ab30..00000000
--- a/tests/models/revgptv4.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import unittest
-from unittest.mock import patch
-from RevChatGPTModelv4 import RevChatGPTModelv4
-
-
-class TestRevChatGPT(unittest.TestCase):
-    def setUp(self):
-        self.access_token = "123"
-        self.model = RevChatGPTModelv4(access_token=self.access_token)
-
-    def test_run(self):
-        prompt = "What is the capital of France?"
-        self.model.start_time = 10
-        self.model.end_time = 20
-        response = self.model.run(prompt)
-        self.assertEqual(response, "The capital of France is Paris.")
-        self.assertEqual(self.model.start_time, 10)
-        self.assertEqual(self.model.end_time, 20)
-
-    def test_generate_summary(self):
-        text = "Hello world. This is some text. It has multiple sentences."
-        summary = self.model.generate_summary(text)
-        self.assertEqual(summary, "")
-
-    @patch("RevChatGPTModelv4.Chatbot.install_plugin")
-    def test_enable_plugin(self, mock_install_plugin):
-        plugin_id = "plugin123"
-        self.model.enable_plugin(plugin_id)
-        mock_install_plugin.assert_called_with(plugin_id=plugin_id)
-
-    @patch("RevChatGPTModelv4.Chatbot.get_plugins")
-    def test_list_plugins(self, mock_get_plugins):
-        mock_get_plugins.return_value = [{"id": "123", "name": "Test Plugin"}]
-        plugins = self.model.list_plugins()
-        self.assertEqual(len(plugins), 1)
-        self.assertEqual(plugins[0]["id"], "123")
-        self.assertEqual(plugins[0]["name"], "Test Plugin")
-
-    @patch("RevChatGPTModelv4.Chatbot.get_conversations")
-    def test_get_conversations(self, mock_get_conversations):
-        self.model.chatbot.get_conversations()
-        mock_get_conversations.assert_called()
-
-    @patch("RevChatGPTModelv4.Chatbot.get_msg_history")
-    def test_get_msg_history(self, mock_get_msg_history):
-        convo_id = "123"
-        self.model.chatbot.get_msg_history(convo_id)
-        mock_get_msg_history.assert_called_with(convo_id)
-
-    @patch("RevChatGPTModelv4.Chatbot.share_conversation")
-    def test_share_conversation(self, mock_share_conversation):
-        self.model.chatbot.share_conversation()
-        mock_share_conversation.assert_called()
-
-    @patch("RevChatGPTModelv4.Chatbot.gen_title")
-    def test_gen_title(self, mock_gen_title):
-        convo_id = "123"
-        message_id = "456"
-        self.model.chatbot.gen_title(convo_id, message_id)
-        mock_gen_title.assert_called_with(convo_id, message_id)
-
-    @patch("RevChatGPTModelv4.Chatbot.change_title")
-    def test_change_title(self, mock_change_title):
-        convo_id = "123"
-        title = "New Title"
-        self.model.chatbot.change_title(convo_id, title)
-        mock_change_title.assert_called_with(convo_id, title)
-
-    @patch("RevChatGPTModelv4.Chatbot.delete_conversation")
-    def test_delete_conversation(self, mock_delete_conversation):
-        convo_id = "123"
-        self.model.chatbot.delete_conversation(convo_id)
-        mock_delete_conversation.assert_called_with(convo_id)
-
-    @patch("RevChatGPTModelv4.Chatbot.clear_conversations")
-    def test_clear_conversations(self, mock_clear_conversations):
-        self.model.chatbot.clear_conversations()
-        mock_clear_conversations.assert_called()
-
-    @patch("RevChatGPTModelv4.Chatbot.rollback_conversation")
-    def test_rollback_conversation(self, mock_rollback_conversation):
-        num = 2
-        self.model.chatbot.rollback_conversation(num)
-        mock_rollback_conversation.assert_called_with(num)
-
-    @patch("RevChatGPTModelv4.Chatbot.reset_chat")
-    def test_reset_chat(self, mock_reset_chat):
-        self.model.chatbot.reset_chat()
-        mock_reset_chat.assert_called()
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/tests/models/LLM.py b/tests/models/test_LLM.py
similarity index 84%
rename from tests/models/LLM.py
rename to tests/models/test_LLM.py
index 20493519..04d6a5f2 100644
--- a/tests/models/LLM.py
+++ b/tests/models/test_LLM.py
@@ -11,11 +11,15 @@ class TestLLM(unittest.TestCase):
     @patch.object(ChatOpenAI, "__init__", return_value=None)
     def setUp(self, mock_hf_init, mock_openai_init):
         self.llm_openai = LLM(openai_api_key="mock_openai_key")
-        self.llm_hf = LLM(hf_repo_id="mock_repo_id", hf_api_token="mock_hf_token")
+        self.llm_hf = LLM(
+            hf_repo_id="mock_repo_id", hf_api_token="mock_hf_token"
+        )
         self.prompt = "Who won the FIFA World Cup in 1998?"
 
     def test_init(self):
-        self.assertEqual(self.llm_openai.openai_api_key, "mock_openai_key")
+        self.assertEqual(
+            self.llm_openai.openai_api_key, "mock_openai_key"
+        )
         self.assertEqual(self.llm_hf.hf_repo_id, "mock_repo_id")
         self.assertEqual(self.llm_hf.hf_api_token, "mock_hf_token")
 
@@ -39,7 +43,9 @@ class TestLLM(unittest.TestCase):
         with self.assertRaises(ValueError):
             LLM(hf_repo_id="mock_repo_id")
 
-    @patch.dict(os.environ, {"HUGGINGFACEHUB_API_TOKEN": "mock_hf_token"})
+    @patch.dict(
+        os.environ, {"HUGGINGFACEHUB_API_TOKEN": "mock_hf_token"}
+    )
     def test_hf_token_from_env(self):
         llm = LLM(hf_repo_id="mock_repo_id")
         self.assertEqual(llm.hf_api_token, "mock_hf_token")
diff --git a/tests/models/ada.py b/tests/models/test_ada.py
similarity index 75%
rename from tests/models/ada.py
rename to tests/models/test_ada.py
index e65e1470..43895e79 100644
--- a/tests/models/ada.py
+++ b/tests/models/test_ada.py
@@ -26,7 +26,9 @@ def test_texts():
 def test_get_ada_embeddings_basic(test_texts):
     with patch("openai.resources.Embeddings.create") as mock_create:
         # Mocking the OpenAI API call
-        mock_create.return_value = {"data": [{"embedding": [0.1, 0.2, 0.3]}]}
+        mock_create.return_value = {
+            "data": [{"embedding": [0.1, 0.2, 0.3]}]
+        }
 
         for text in test_texts:
             embedding = get_ada_embeddings(text)
@@ -36,7 +38,8 @@ def test_get_ada_embeddings_basic(test_texts):
                 0.3,
             ], "Embedding does not match expected output"
             mock_create.assert_called_with(
-                input=[text.replace("\n", " ")], model="text-embedding-ada-002"
+                input=[text.replace("\n", " ")],
+                model="text-embedding-ada-002",
             )
 
 
@@ -44,16 +47,28 @@ def test_get_ada_embeddings_basic(test_texts):
 @pytest.mark.parametrize(
     "text, model, expected_call_model",
     [
-        ("Hello World", "text-embedding-ada-002", "text-embedding-ada-002"),
-        ("Hello World", "text-embedding-ada-001", "text-embedding-ada-001"),
+        (
+            "Hello World",
+            "text-embedding-ada-002",
+            "text-embedding-ada-002",
+        ),
+        (
+            "Hello World",
+            "text-embedding-ada-001",
+            "text-embedding-ada-001",
+        ),
     ],
 )
 def test_get_ada_embeddings_models(text, model, expected_call_model):
     with patch("openai.resources.Embeddings.create") as mock_create:
-        mock_create.return_value = {"data": [{"embedding": [0.1, 0.2, 0.3]}]}
+        mock_create.return_value = {
+            "data": [{"embedding": [0.1, 0.2, 0.3]}]
+        }
 
         _ = get_ada_embeddings(text, model=model)
-        mock_create.assert_called_with(input=[text], model=expected_call_model)
+        mock_create.assert_called_with(
+            input=[text], model=expected_call_model
+        )
 
 
 # Exception Test
diff --git a/tests/models/anthropic.py b/tests/models/test_anthropic.py
similarity index 85%
rename from tests/models/anthropic.py
rename to tests/models/test_anthropic.py
index e2447614..cc48479a 100644
--- a/tests/models/anthropic.py
+++ b/tests/models/test_anthropic.py
@@ -11,7 +11,9 @@ class MockAnthropicClient:
     def __init__(self, *args, **kwargs):
         pass
 
-    def completions_create(self, prompt, stop_sequences, stream, **kwargs):
+    def completions_create(
+        self, prompt, stop_sequences, stream, **kwargs
+    ):
         return MockAnthropicResponse()
 
 
@@ -43,7 +45,10 @@ def test_anthropic_init_default_values(anthropic_instance):
     assert anthropic_instance.top_p is None
     assert anthropic_instance.streaming is False
     assert anthropic_instance.default_request_timeout == 600
-    assert anthropic_instance.anthropic_api_url == "https://test.anthropic.com"
+    assert (
+        anthropic_instance.anthropic_api_url
+        == "https://test.anthropic.com"
+    )
     assert anthropic_instance.anthropic_api_key == "test_api_key"
 
 
@@ -74,7 +79,9 @@ def test_anthropic_default_params(anthropic_instance):
     }
 
 
-def test_anthropic_run(mock_anthropic_env, mock_requests_post, anthropic_instance):
+def test_anthropic_run(
+    mock_anthropic_env, mock_requests_post, anthropic_instance
+):
     mock_response = Mock()
     mock_response.json.return_value = {"completion": "Generated text"}
     mock_requests_post.return_value = mock_response
@@ -98,7 +105,9 @@ def test_anthropic_run(mock_anthropic_env, mock_requests_post, anthropic_instanc
     )
 
 
-def test_anthropic_call(mock_anthropic_env, mock_requests_post, anthropic_instance):
+def test_anthropic_call(
+    mock_anthropic_env, mock_requests_post, anthropic_instance
+):
     mock_response = Mock()
     mock_response.json.return_value = {"completion": "Generated text"}
     mock_requests_post.return_value = mock_response
@@ -164,7 +173,9 @@ def test_anthropic_async_call_method(anthropic_instance):
 
 
 def test_anthropic_async_stream_method(anthropic_instance):
-    async_generator = anthropic_instance.async_stream("Translate to French.")
+    async_generator = anthropic_instance.async_stream(
+        "Translate to French."
+    )
     for token in async_generator:
         assert isinstance(token, str)
 
@@ -188,23 +199,31 @@ def test_anthropic_wrap_prompt(anthropic_instance):
 def test_anthropic_convert_prompt(anthropic_instance):
     prompt = "What is the meaning of life?"
     converted_prompt = anthropic_instance.convert_prompt(prompt)
-    assert converted_prompt.startswith(anthropic_instance.HUMAN_PROMPT)
+    assert converted_prompt.startswith(
+        anthropic_instance.HUMAN_PROMPT
+    )
     assert converted_prompt.endswith(anthropic_instance.AI_PROMPT)
 
 
 def test_anthropic_call_with_stop(anthropic_instance):
-    response = anthropic_instance("Translate to French.", stop=["stop1", "stop2"])
+    response = anthropic_instance(
+        "Translate to French.", stop=["stop1", "stop2"]
+    )
     assert response == "Mocked Response from Anthropic"
 
 
 def test_anthropic_stream_with_stop(anthropic_instance):
-    generator = anthropic_instance.stream("Write a story.", stop=["stop1", "stop2"])
+    generator = anthropic_instance.stream(
+        "Write a story.", stop=["stop1", "stop2"]
+    )
     for token in generator:
         assert isinstance(token, str)
 
 
 def test_anthropic_async_call_with_stop(anthropic_instance):
-    response = anthropic_instance.async_call("Tell me a joke.", stop=["stop1", "stop2"])
+    response = anthropic_instance.async_call(
+        "Tell me a joke.", stop=["stop1", "stop2"]
+    )
     assert response == "Mocked Response from Anthropic"
 
 
@@ -216,21 +235,27 @@ def test_anthropic_async_stream_with_stop(anthropic_instance):
         assert isinstance(token, str)
 
 
-def test_anthropic_get_num_tokens_with_count_tokens(anthropic_instance):
+def test_anthropic_get_num_tokens_with_count_tokens(
+    anthropic_instance,
+):
     anthropic_instance.count_tokens = Mock(return_value=10)
     text = "This is a test sentence."
     num_tokens = anthropic_instance.get_num_tokens(text)
     assert num_tokens == 10
 
 
-def test_anthropic_get_num_tokens_without_count_tokens(anthropic_instance):
+def test_anthropic_get_num_tokens_without_count_tokens(
+    anthropic_instance,
+):
     del anthropic_instance.count_tokens
     with pytest.raises(NameError):
         text = "This is a test sentence."
         anthropic_instance.get_num_tokens(text)
 
 
-def test_anthropic_wrap_prompt_without_human_ai_prompt(anthropic_instance):
+def test_anthropic_wrap_prompt_without_human_ai_prompt(
+    anthropic_instance,
+):
     del anthropic_instance.HUMAN_PROMPT
     del anthropic_instance.AI_PROMPT
     prompt = "What is the meaning of life?"
diff --git a/tests/models/auto_temp.py b/tests/models/test_auto_temp.py
similarity index 92%
rename from tests/models/auto_temp.py
rename to tests/models/test_auto_temp.py
index bd37e5bb..7937d0dc 100644
--- a/tests/models/auto_temp.py
+++ b/tests/models/test_auto_temp.py
@@ -47,9 +47,13 @@ def test_run_auto_select(auto_temp_agent):
 def test_run_no_scores(auto_temp_agent):
     task = "Invalid task."
     temperature_string = "0.4,0.6,0.8,1.0,1.2,1.4"
-    with ThreadPoolExecutor(max_workers=auto_temp_agent.max_workers) as executor:
+    with ThreadPoolExecutor(
+        max_workers=auto_temp_agent.max_workers
+    ) as executor:
         with patch.object(
-            executor, "submit", side_effect=[None, None, None, None, None, None]
+            executor,
+            "submit",
+            side_effect=[None, None, None, None, None, None],
         ):
             result = auto_temp_agent.run(task, temperature_string)
             assert result == "No valid outputs generated."
diff --git a/tests/models/bioclip.py b/tests/models/test_bioclip.py
similarity index 91%
rename from tests/models/bioclip.py
rename to tests/models/test_bioclip.py
index 50a65570..99e1e343 100644
--- a/tests/models/bioclip.py
+++ b/tests/models/test_bioclip.py
@@ -14,7 +14,9 @@ def sample_image_path():
 
 @pytest.fixture
 def clip_instance():
-    return BioClip("microsoft/BiomedCLIP-PubMedBERT_256-vit_base_patch16_224")
+    return BioClip(
+        "microsoft/BiomedCLIP-PubMedBERT_256-vit_base_patch16_224"
+    )
 
 
 # Basic tests for the BioClip class
@@ -44,12 +46,16 @@ def test_clip_call_method(clip_instance, sample_image_path):
     assert len(result) == len(labels)
 
 
-def test_clip_plot_image_with_metadata(clip_instance, sample_image_path):
+def test_clip_plot_image_with_metadata(
+    clip_instance, sample_image_path
+):
     metadata = {
         "filename": "sample_image.jpg",
         "top_probs": {"label1": 0.75, "label2": 0.65},
     }
-    clip_instance.plot_image_with_metadata(sample_image_path, metadata)
+    clip_instance.plot_image_with_metadata(
+        sample_image_path, metadata
+    )
 
 
 # More test cases can be added to cover additional functionality and edge cases
@@ -127,7 +133,9 @@ def test_clip_multiple_images(clip_instance, sample_image_path):
 
 
 # Test model inference performance
-def test_clip_inference_performance(clip_instance, sample_image_path, benchmark):
+def test_clip_inference_performance(
+    clip_instance, sample_image_path, benchmark
+):
     labels = [
         "adenocarcinoma histopathology",
         "brain MRI",
@@ -145,7 +153,9 @@ def test_clip_inference_performance(clip_instance, sample_image_path, benchmark)
 
 
 # Test different preprocessing pipelines
-def test_clip_preprocessing_pipelines(clip_instance, sample_image_path):
+def test_clip_preprocessing_pipelines(
+    clip_instance, sample_image_path
+):
     labels = ["label1", "label2"]
     image = Image.open(sample_image_path)
 
diff --git a/tests/models/biogpt.py b/tests/models/test_biogpt.py
similarity index 90%
rename from tests/models/biogpt.py
rename to tests/models/test_biogpt.py
index f420292b..38be125d 100644
--- a/tests/models/biogpt.py
+++ b/tests/models/test_biogpt.py
@@ -46,7 +46,10 @@ def test_cell_biology_response(biogpt_instance):
 
 # 40. Test for a question about protein structure
 def test_protein_structure_response(biogpt_instance):
-    question = "What's the difference between alpha helix and beta sheet structures in proteins?"
+    question = (
+        "What's the difference between alpha helix and beta sheet"
+        " structures in proteins?"
+    )
     response = biogpt_instance(question)
     assert response and isinstance(response, str)
 
@@ -74,7 +77,9 @@ def test_bioinformatics_response(biogpt_instance):
 
 # 44. Test for a neuroscience question
 def test_neuroscience_response(biogpt_instance):
-    question = "Explain the function of synapses in the nervous system."
+    question = (
+        "Explain the function of synapses in the nervous system."
+    )
     response = biogpt_instance(question)
     assert response and isinstance(response, str)
 
@@ -154,7 +159,9 @@ def test_get_config_return_type(biogpt_instance):
 # 28. Test saving model functionality by checking if files are created
 @patch.object(BioGptForCausalLM, "save_pretrained")
 @patch.object(BioGptTokenizer, "save_pretrained")
-def test_save_model(mock_save_model, mock_save_tokenizer, biogpt_instance):
+def test_save_model(
+    mock_save_model, mock_save_tokenizer, biogpt_instance
+):
     path = "test_path"
     biogpt_instance.save_model(path)
     mock_save_model.assert_called_once_with(path)
@@ -164,7 +171,9 @@ def test_save_model(mock_save_model, mock_save_tokenizer, biogpt_instance):
 # 29. Test loading model from path
 @patch.object(BioGptForCausalLM, "from_pretrained")
 @patch.object(BioGptTokenizer, "from_pretrained")
-def test_load_from_path(mock_load_model, mock_load_tokenizer, biogpt_instance):
+def test_load_from_path(
+    mock_load_model, mock_load_tokenizer, biogpt_instance
+):
     path = "test_path"
     biogpt_instance.load_from_path(path)
     mock_load_model.assert_called_once_with(path)
@@ -181,7 +190,9 @@ def test_print_model_metadata(biogpt_instance):
 
 # 31. Test that beam_search_decoding uses the correct number of beams
 @patch.object(BioGptForCausalLM, "generate")
-def test_beam_search_decoding_num_beams(mock_generate, biogpt_instance):
+def test_beam_search_decoding_num_beams(
+    mock_generate, biogpt_instance
+):
     biogpt_instance.beam_search_decoding("test_sentence", num_beams=7)
     _, kwargs = mock_generate.call_args
     assert kwargs["num_beams"] == 7
@@ -189,8 +200,12 @@ def test_beam_search_decoding_num_beams(mock_generate, biogpt_instance):
 
 # 32. Test if beam_search_decoding handles early_stopping
 @patch.object(BioGptForCausalLM, "generate")
-def test_beam_search_decoding_early_stopping(mock_generate, biogpt_instance):
-    biogpt_instance.beam_search_decoding("test_sentence", early_stopping=False)
+def test_beam_search_decoding_early_stopping(
+    mock_generate, biogpt_instance
+):
+    biogpt_instance.beam_search_decoding(
+        "test_sentence", early_stopping=False
+    )
     _, kwargs = mock_generate.call_args
     assert kwargs["early_stopping"] is False
 
diff --git a/tests/models/cohere.py b/tests/models/test_cohere.py
similarity index 77%
rename from tests/models/cohere.py
rename to tests/models/test_cohere.py
index d1bea935..5e6fc948 100644
--- a/tests/models/cohere.py
+++ b/tests/models/test_cohere.py
@@ -41,7 +41,9 @@ def test_cohere_async_api_error_handling(cohere_instance):
     cohere_instance.model = "base"
     cohere_instance.cohere_api_key = "invalid-api-key"
     with pytest.raises(Exception):
-        cohere_instance.async_call("Error handling with invalid API key.")
+        cohere_instance.async_call(
+            "Error handling with invalid API key."
+        )
 
 
 def test_cohere_stream_api_error_handling(cohere_instance):
@@ -49,7 +51,9 @@ def test_cohere_stream_api_error_handling(cohere_instance):
     cohere_instance.model = "base"
     cohere_instance.cohere_api_key = "invalid-api-key"
     with pytest.raises(Exception):
-        generator = cohere_instance.stream("Error handling with invalid API key.")
+        generator = cohere_instance.stream(
+            "Error handling with invalid API key."
+        )
         for token in generator:
             pass
 
@@ -89,18 +93,24 @@ def test_cohere_convert_prompt(cohere_instance):
 
 
 def test_cohere_call_with_stop(cohere_instance):
-    response = cohere_instance("Translate to French.", stop=["stop1", "stop2"])
+    response = cohere_instance(
+        "Translate to French.", stop=["stop1", "stop2"]
+    )
     assert response == "Mocked Response from Cohere"
 
 
 def test_cohere_stream_with_stop(cohere_instance):
-    generator = cohere_instance.stream("Write a story.", stop=["stop1", "stop2"])
+    generator = cohere_instance.stream(
+        "Write a story.", stop=["stop1", "stop2"]
+    )
     for token in generator:
         assert isinstance(token, str)
 
 
 def test_cohere_async_call_with_stop(cohere_instance):
-    response = cohere_instance.async_call("Tell me a joke.", stop=["stop1", "stop2"])
+    response = cohere_instance.async_call(
+        "Tell me a joke.", stop=["stop1", "stop2"]
+    )
     assert response == "Mocked Response from Cohere"
 
 
@@ -141,14 +151,20 @@ def test_base_cohere_import():
 
 
 def test_base_cohere_validate_environment():
-    values = {"cohere_api_key": "my-api-key", "user_agent": "langchain"}
+    values = {
+        "cohere_api_key": "my-api-key",
+        "user_agent": "langchain",
+    }
     validated_values = BaseCohere.validate_environment(values)
     assert "client" in validated_values
     assert "async_client" in validated_values
 
 
 def test_base_cohere_validate_environment_without_cohere():
-    values = {"cohere_api_key": "my-api-key", "user_agent": "langchain"}
+    values = {
+        "cohere_api_key": "my-api-key",
+        "user_agent": "langchain",
+    }
     with patch.dict("sys.modules", {"cohere": None}):
         with pytest.raises(ImportError):
             BaseCohere.validate_environment(values)
@@ -157,8 +173,12 @@ def test_base_cohere_validate_environment_without_cohere():
 # Test cases for benchmarking generations with various models
 def test_cohere_generate_with_command_light(cohere_instance):
     cohere_instance.model = "command-light"
-    response = cohere_instance("Generate text with Command Light model.")
-    assert response.startswith("Generated text with Command Light model")
+    response = cohere_instance(
+        "Generate text with Command Light model."
+    )
+    assert response.startswith(
+        "Generated text with Command Light model"
+    )
 
 
 def test_cohere_generate_with_command(cohere_instance):
@@ -181,41 +201,67 @@ def test_cohere_generate_with_base(cohere_instance):
 
 def test_cohere_generate_with_embed_english_v2(cohere_instance):
     cohere_instance.model = "embed-english-v2.0"
-    response = cohere_instance("Generate embeddings with English v2.0 model.")
-    assert response.startswith("Generated embeddings with English v2.0 model")
+    response = cohere_instance(
+        "Generate embeddings with English v2.0 model."
+    )
+    assert response.startswith(
+        "Generated embeddings with English v2.0 model"
+    )
 
 
 def test_cohere_generate_with_embed_english_light_v2(cohere_instance):
     cohere_instance.model = "embed-english-light-v2.0"
-    response = cohere_instance("Generate embeddings with English Light v2.0 model.")
-    assert response.startswith("Generated embeddings with English Light v2.0 model")
+    response = cohere_instance(
+        "Generate embeddings with English Light v2.0 model."
+    )
+    assert response.startswith(
+        "Generated embeddings with English Light v2.0 model"
+    )
 
 
 def test_cohere_generate_with_embed_multilingual_v2(cohere_instance):
     cohere_instance.model = "embed-multilingual-v2.0"
-    response = cohere_instance("Generate embeddings with Multilingual v2.0 model.")
-    assert response.startswith("Generated embeddings with Multilingual v2.0 model")
+    response = cohere_instance(
+        "Generate embeddings with Multilingual v2.0 model."
+    )
+    assert response.startswith(
+        "Generated embeddings with Multilingual v2.0 model"
+    )
 
 
 def test_cohere_generate_with_embed_english_v3(cohere_instance):
     cohere_instance.model = "embed-english-v3.0"
-    response = cohere_instance("Generate embeddings with English v3.0 model.")
-    assert response.startswith("Generated embeddings with English v3.0 model")
+    response = cohere_instance(
+        "Generate embeddings with English v3.0 model."
+    )
+    assert response.startswith(
+        "Generated embeddings with English v3.0 model"
+    )
 
 
 def test_cohere_generate_with_embed_english_light_v3(cohere_instance):
     cohere_instance.model = "embed-english-light-v3.0"
-    response = cohere_instance("Generate embeddings with English Light v3.0 model.")
-    assert response.startswith("Generated embeddings with English Light v3.0 model")
+    response = cohere_instance(
+        "Generate embeddings with English Light v3.0 model."
+    )
+    assert response.startswith(
+        "Generated embeddings with English Light v3.0 model"
+    )
 
 
 def test_cohere_generate_with_embed_multilingual_v3(cohere_instance):
     cohere_instance.model = "embed-multilingual-v3.0"
-    response = cohere_instance("Generate embeddings with Multilingual v3.0 model.")
-    assert response.startswith("Generated embeddings with Multilingual v3.0 model")
+    response = cohere_instance(
+        "Generate embeddings with Multilingual v3.0 model."
+    )
+    assert response.startswith(
+        "Generated embeddings with Multilingual v3.0 model"
+    )
 
 
-def test_cohere_generate_with_embed_multilingual_light_v3(cohere_instance):
+def test_cohere_generate_with_embed_multilingual_light_v3(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-light-v3.0"
     response = cohere_instance(
         "Generate embeddings with Multilingual Light v3.0 model."
@@ -252,13 +298,17 @@ def test_cohere_call_with_embed_english_v3_model(cohere_instance):
     assert isinstance(response, str)
 
 
-def test_cohere_call_with_embed_multilingual_v2_model(cohere_instance):
+def test_cohere_call_with_embed_multilingual_v2_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v2.0"
     response = cohere_instance("Translate to French.")
     assert isinstance(response, str)
 
 
-def test_cohere_call_with_embed_multilingual_v3_model(cohere_instance):
+def test_cohere_call_with_embed_multilingual_v3_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v3.0"
     response = cohere_instance("Translate to French.")
     assert isinstance(response, str)
@@ -278,7 +328,9 @@ def test_cohere_call_with_long_prompt(cohere_instance):
 
 def test_cohere_call_with_max_tokens_limit_exceeded(cohere_instance):
     cohere_instance.max_tokens = 10
-    prompt = "This is a test prompt that will exceed the max tokens limit."
+    prompt = (
+        "This is a test prompt that will exceed the max tokens limit."
+    )
     with pytest.raises(ValueError):
         cohere_instance(prompt)
 
@@ -311,14 +363,18 @@ def test_cohere_stream_with_embed_english_v3_model(cohere_instance):
         assert isinstance(token, str)
 
 
-def test_cohere_stream_with_embed_multilingual_v2_model(cohere_instance):
+def test_cohere_stream_with_embed_multilingual_v2_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v2.0"
     generator = cohere_instance.stream("Write a story.")
     for token in generator:
         assert isinstance(token, str)
 
 
-def test_cohere_stream_with_embed_multilingual_v3_model(cohere_instance):
+def test_cohere_stream_with_embed_multilingual_v3_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v3.0"
     generator = cohere_instance.stream("Write a story.")
     for token in generator:
@@ -337,25 +393,33 @@ def test_cohere_async_call_with_base_model(cohere_instance):
     assert isinstance(response, str)
 
 
-def test_cohere_async_call_with_embed_english_v2_model(cohere_instance):
+def test_cohere_async_call_with_embed_english_v2_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-english-v2.0"
     response = cohere_instance.async_call("Translate to French.")
     assert isinstance(response, str)
 
 
-def test_cohere_async_call_with_embed_english_v3_model(cohere_instance):
+def test_cohere_async_call_with_embed_english_v3_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-english-v3.0"
     response = cohere_instance.async_call("Translate to French.")
     assert isinstance(response, str)
 
 
-def test_cohere_async_call_with_embed_multilingual_v2_model(cohere_instance):
+def test_cohere_async_call_with_embed_multilingual_v2_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v2.0"
     response = cohere_instance.async_call("Translate to French.")
     assert isinstance(response, str)
 
 
-def test_cohere_async_call_with_embed_multilingual_v3_model(cohere_instance):
+def test_cohere_async_call_with_embed_multilingual_v3_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v3.0"
     response = cohere_instance.async_call("Translate to French.")
     assert isinstance(response, str)
@@ -375,28 +439,36 @@ def test_cohere_async_stream_with_base_model(cohere_instance):
         assert isinstance(token, str)
 
 
-def test_cohere_async_stream_with_embed_english_v2_model(cohere_instance):
+def test_cohere_async_stream_with_embed_english_v2_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-english-v2.0"
     async_generator = cohere_instance.async_stream("Write a story.")
     for token in async_generator:
         assert isinstance(token, str)
 
 
-def test_cohere_async_stream_with_embed_english_v3_model(cohere_instance):
+def test_cohere_async_stream_with_embed_english_v3_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-english-v3.0"
     async_generator = cohere_instance.async_stream("Write a story.")
     for token in async_generator:
         assert isinstance(token, str)
 
 
-def test_cohere_async_stream_with_embed_multilingual_v2_model(cohere_instance):
+def test_cohere_async_stream_with_embed_multilingual_v2_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v2.0"
     async_generator = cohere_instance.async_stream("Write a story.")
     for token in async_generator:
         assert isinstance(token, str)
 
 
-def test_cohere_async_stream_with_embed_multilingual_v3_model(cohere_instance):
+def test_cohere_async_stream_with_embed_multilingual_v3_model(
+    cohere_instance,
+):
     cohere_instance.model = "embed-multilingual-v3.0"
     async_generator = cohere_instance.async_stream("Write a story.")
     for token in async_generator:
@@ -406,7 +478,9 @@ def test_cohere_async_stream_with_embed_multilingual_v3_model(cohere_instance):
 def test_cohere_representation_model_embedding(cohere_instance):
     # Test using the Representation model for text embedding
     cohere_instance.model = "embed-english-v3.0"
-    embedding = cohere_instance.embed("Generate an embedding for this text.")
+    embedding = cohere_instance.embed(
+        "Generate an embedding for this text."
+    )
     assert isinstance(embedding, list)
     assert len(embedding) > 0
 
@@ -420,18 +494,26 @@ def test_cohere_representation_model_classification(cohere_instance):
     assert "score" in classification
 
 
-def test_cohere_representation_model_language_detection(cohere_instance):
+def test_cohere_representation_model_language_detection(
+    cohere_instance,
+):
     # Test using the Representation model for language detection
     cohere_instance.model = "embed-english-v3.0"
-    language = cohere_instance.detect_language("Detect the language of this text.")
+    language = cohere_instance.detect_language(
+        "Detect the language of this text."
+    )
     assert isinstance(language, str)
 
 
-def test_cohere_representation_model_max_tokens_limit_exceeded(cohere_instance):
+def test_cohere_representation_model_max_tokens_limit_exceeded(
+    cohere_instance,
+):
     # Test handling max tokens limit exceeded error
     cohere_instance.model = "embed-english-v3.0"
     cohere_instance.max_tokens = 10
-    prompt = "This is a test prompt that will exceed the max tokens limit."
+    prompt = (
+        "This is a test prompt that will exceed the max tokens limit."
+    )
     with pytest.raises(ValueError):
         cohere_instance.embed(prompt)
 
@@ -439,24 +521,34 @@ def test_cohere_representation_model_max_tokens_limit_exceeded(cohere_instance):
 # Add more production-grade test cases based on real-world scenarios
 
 
-def test_cohere_representation_model_multilingual_embedding(cohere_instance):
+def test_cohere_representation_model_multilingual_embedding(
+    cohere_instance,
+):
     # Test using the Representation model for multilingual text embedding
     cohere_instance.model = "embed-multilingual-v3.0"
-    embedding = cohere_instance.embed("Generate multilingual embeddings.")
+    embedding = cohere_instance.embed(
+        "Generate multilingual embeddings."
+    )
     assert isinstance(embedding, list)
     assert len(embedding) > 0
 
 
-def test_cohere_representation_model_multilingual_classification(cohere_instance):
+def test_cohere_representation_model_multilingual_classification(
+    cohere_instance,
+):
     # Test using the Representation model for multilingual text classification
     cohere_instance.model = "embed-multilingual-v3.0"
-    classification = cohere_instance.classify("Classify multilingual text.")
+    classification = cohere_instance.classify(
+        "Classify multilingual text."
+    )
     assert isinstance(classification, dict)
     assert "class" in classification
     assert "score" in classification
 
 
-def test_cohere_representation_model_multilingual_language_detection(cohere_instance):
+def test_cohere_representation_model_multilingual_language_detection(
+    cohere_instance,
+):
     # Test using the Representation model for multilingual language detection
     cohere_instance.model = "embed-multilingual-v3.0"
     language = cohere_instance.detect_language(
@@ -471,23 +563,34 @@ def test_cohere_representation_model_multilingual_max_tokens_limit_exceeded(
     # Test handling max tokens limit exceeded error for multilingual model
     cohere_instance.model = "embed-multilingual-v3.0"
     cohere_instance.max_tokens = 10
-    prompt = "This is a test prompt that will exceed the max tokens limit for multilingual model."
+    prompt = (
+        "This is a test prompt that will exceed the max tokens limit"
+        " for multilingual model."
+    )
     with pytest.raises(ValueError):
         cohere_instance.embed(prompt)
 
 
-def test_cohere_representation_model_multilingual_light_embedding(cohere_instance):
+def test_cohere_representation_model_multilingual_light_embedding(
+    cohere_instance,
+):
     # Test using the Representation model for multilingual light text embedding
     cohere_instance.model = "embed-multilingual-light-v3.0"
-    embedding = cohere_instance.embed("Generate multilingual light embeddings.")
+    embedding = cohere_instance.embed(
+        "Generate multilingual light embeddings."
+    )
     assert isinstance(embedding, list)
     assert len(embedding) > 0
 
 
-def test_cohere_representation_model_multilingual_light_classification(cohere_instance):
+def test_cohere_representation_model_multilingual_light_classification(
+    cohere_instance,
+):
     # Test using the Representation model for multilingual light text classification
     cohere_instance.model = "embed-multilingual-light-v3.0"
-    classification = cohere_instance.classify("Classify multilingual light text.")
+    classification = cohere_instance.classify(
+        "Classify multilingual light text."
+    )
     assert isinstance(classification, dict)
     assert "class" in classification
     assert "score" in classification
@@ -510,7 +613,10 @@ def test_cohere_representation_model_multilingual_light_max_tokens_limit_exceede
     # Test handling max tokens limit exceeded error for multilingual light model
     cohere_instance.model = "embed-multilingual-light-v3.0"
     cohere_instance.max_tokens = 10
-    prompt = "This is a test prompt that will exceed the max tokens limit for multilingual light model."
+    prompt = (
+        "This is a test prompt that will exceed the max tokens limit"
+        " for multilingual light model."
+    )
     with pytest.raises(ValueError):
         cohere_instance.embed(prompt)
 
@@ -518,14 +624,18 @@ def test_cohere_representation_model_multilingual_light_max_tokens_limit_exceede
 def test_cohere_command_light_model(cohere_instance):
     # Test using the Command Light model for text generation
     cohere_instance.model = "command-light"
-    response = cohere_instance("Generate text using Command Light model.")
+    response = cohere_instance(
+        "Generate text using Command Light model."
+    )
     assert isinstance(response, str)
 
 
 def test_cohere_base_light_model(cohere_instance):
     # Test using the Base Light model for text generation
     cohere_instance.model = "base-light"
-    response = cohere_instance("Generate text using Base Light model.")
+    response = cohere_instance(
+        "Generate text using Base Light model."
+    )
     assert isinstance(response, str)
 
 
@@ -536,7 +646,9 @@ def test_cohere_generate_summarize_endpoint(cohere_instance):
     assert isinstance(response, str)
 
 
-def test_cohere_representation_model_english_embedding(cohere_instance):
+def test_cohere_representation_model_english_embedding(
+    cohere_instance,
+):
     # Test using the Representation model for English text embedding
     cohere_instance.model = "embed-english-v3.0"
     embedding = cohere_instance.embed("Generate English embeddings.")
@@ -544,51 +656,72 @@ def test_cohere_representation_model_english_embedding(cohere_instance):
     assert len(embedding) > 0
 
 
-def test_cohere_representation_model_english_classification(cohere_instance):
+def test_cohere_representation_model_english_classification(
+    cohere_instance,
+):
     # Test using the Representation model for English text classification
     cohere_instance.model = "embed-english-v3.0"
-    classification = cohere_instance.classify("Classify English text.")
+    classification = cohere_instance.classify(
+        "Classify English text."
+    )
     assert isinstance(classification, dict)
     assert "class" in classification
     assert "score" in classification
 
 
-def test_cohere_representation_model_english_language_detection(cohere_instance):
+def test_cohere_representation_model_english_language_detection(
+    cohere_instance,
+):
     # Test using the Representation model for English language detection
     cohere_instance.model = "embed-english-v3.0"
-    language = cohere_instance.detect_language("Detect the language of English text.")
+    language = cohere_instance.detect_language(
+        "Detect the language of English text."
+    )
     assert isinstance(language, str)
 
 
-def test_cohere_representation_model_english_max_tokens_limit_exceeded(cohere_instance):
+def test_cohere_representation_model_english_max_tokens_limit_exceeded(
+    cohere_instance,
+):
     # Test handling max tokens limit exceeded error for English model
     cohere_instance.model = "embed-english-v3.0"
     cohere_instance.max_tokens = 10
     prompt = (
-        "This is a test prompt that will exceed the max tokens limit for English model."
+        "This is a test prompt that will exceed the max tokens limit"
+        " for English model."
     )
     with pytest.raises(ValueError):
         cohere_instance.embed(prompt)
 
 
-def test_cohere_representation_model_english_light_embedding(cohere_instance):
+def test_cohere_representation_model_english_light_embedding(
+    cohere_instance,
+):
     # Test using the Representation model for English light text embedding
     cohere_instance.model = "embed-english-light-v3.0"
-    embedding = cohere_instance.embed("Generate English light embeddings.")
+    embedding = cohere_instance.embed(
+        "Generate English light embeddings."
+    )
     assert isinstance(embedding, list)
     assert len(embedding) > 0
 
 
-def test_cohere_representation_model_english_light_classification(cohere_instance):
+def test_cohere_representation_model_english_light_classification(
+    cohere_instance,
+):
     # Test using the Representation model for English light text classification
     cohere_instance.model = "embed-english-light-v3.0"
-    classification = cohere_instance.classify("Classify English light text.")
+    classification = cohere_instance.classify(
+        "Classify English light text."
+    )
     assert isinstance(classification, dict)
     assert "class" in classification
     assert "score" in classification
 
 
-def test_cohere_representation_model_english_light_language_detection(cohere_instance):
+def test_cohere_representation_model_english_light_language_detection(
+    cohere_instance,
+):
     # Test using the Representation model for English light language detection
     cohere_instance.model = "embed-english-light-v3.0"
     language = cohere_instance.detect_language(
@@ -603,7 +736,10 @@ def test_cohere_representation_model_english_light_max_tokens_limit_exceeded(
     # Test handling max tokens limit exceeded error for English light model
     cohere_instance.model = "embed-english-light-v3.0"
     cohere_instance.max_tokens = 10
-    prompt = "This is a test prompt that will exceed the max tokens limit for English light model."
+    prompt = (
+        "This is a test prompt that will exceed the max tokens limit"
+        " for English light model."
+    )
     with pytest.raises(ValueError):
         cohere_instance.embed(prompt)
 
@@ -611,7 +747,9 @@ def test_cohere_representation_model_english_light_max_tokens_limit_exceeded(
 def test_cohere_command_model(cohere_instance):
     # Test using the Command model for text generation
     cohere_instance.model = "command"
-    response = cohere_instance("Generate text using the Command model.")
+    response = cohere_instance(
+        "Generate text using the Command model."
+    )
     assert isinstance(response, str)
 
 
@@ -625,7 +763,9 @@ def test_cohere_invalid_model(cohere_instance):
         cohere_instance("Generate text using an invalid model.")
 
 
-def test_cohere_base_model_generation_with_max_tokens(cohere_instance):
+def test_cohere_base_model_generation_with_max_tokens(
+    cohere_instance,
+):
     # Test generating text using the base model with a specified max_tokens limit
     cohere_instance.model = "base"
     cohere_instance.max_tokens = 20
diff --git a/tests/models/dalle3.py b/tests/models/test_dalle3.py
similarity index 75%
rename from tests/models/dalle3.py
rename to tests/models/test_dalle3.py
index a23d077e..00ba7bc9 100644
--- a/tests/models/dalle3.py
+++ b/tests/models/test_dalle3.py
@@ -23,9 +23,7 @@ def dalle3(mock_openai_client):
 def test_dalle3_call_success(dalle3, mock_openai_client):
     # Arrange
     task = "A painting of a dog"
-    expected_img_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    )
+    expected_img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
     mock_openai_client.images.generate.return_value = Mock(
         data=[Mock(url=expected_img_url)]
     )
@@ -35,7 +33,9 @@ def test_dalle3_call_success(dalle3, mock_openai_client):
 
     # Assert
     assert img_url == expected_img_url
-    mock_openai_client.images.generate.assert_called_once_with(prompt=task, n=4)
+    mock_openai_client.images.generate.assert_called_once_with(
+        prompt=task, n=4
+    )
 
 
 def test_dalle3_call_failure(dalle3, mock_openai_client, capsys):
@@ -45,7 +45,9 @@ def test_dalle3_call_failure(dalle3, mock_openai_client, capsys):
 
     # Mocking OpenAIError
     mock_openai_client.images.generate.side_effect = OpenAIError(
-        expected_error_message, http_status=500, error="Internal Server Error"
+        expected_error_message,
+        http_status=500,
+        error="Internal Server Error",
     )
 
     # Act and assert
@@ -53,7 +55,9 @@ def test_dalle3_call_failure(dalle3, mock_openai_client, capsys):
         dalle3(task)
 
     assert str(excinfo.value) == expected_error_message
-    mock_openai_client.images.generate.assert_called_once_with(prompt=task, n=4)
+    mock_openai_client.images.generate.assert_called_once_with(
+        prompt=task, n=4
+    )
 
     # Ensure the error message is printed in red
     captured = capsys.readouterr()
@@ -63,9 +67,7 @@ def test_dalle3_call_failure(dalle3, mock_openai_client, capsys):
 def test_dalle3_create_variations_success(dalle3, mock_openai_client):
     # Arrange
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    expected_variation_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_02ABCDE.png"
-    )
+    expected_variation_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_02ABCDE.png"
     mock_openai_client.images.create_variation.return_value = Mock(
         data=[Mock(url=expected_variation_url)]
     )
@@ -82,14 +84,20 @@ def test_dalle3_create_variations_success(dalle3, mock_openai_client):
     assert kwargs["size"] == "1024x1024"
 
 
-def test_dalle3_create_variations_failure(dalle3, mock_openai_client, capsys):
+def test_dalle3_create_variations_failure(
+    dalle3, mock_openai_client, capsys
+):
     # Arrange
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
     expected_error_message = "Error running Dalle3: API Error"
 
     # Mocking OpenAIError
-    mock_openai_client.images.create_variation.side_effect = OpenAIError(
-        expected_error_message, http_status=500, error="Internal Server Error"
+    mock_openai_client.images.create_variation.side_effect = (
+        OpenAIError(
+            expected_error_message,
+            http_status=500,
+            error="Internal Server Error",
+        )
     )
 
     # Act and assert
@@ -154,9 +162,7 @@ def test_dalle3_convert_to_bytesio():
 def test_dalle3_call_multiple_times(dalle3, mock_openai_client):
     # Arrange
     task = "A painting of a dog"
-    expected_img_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    )
+    expected_img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
     mock_openai_client.images.generate.return_value = Mock(
         data=[Mock(url=expected_img_url)]
     )
@@ -176,7 +182,9 @@ def test_dalle3_call_with_large_input(dalle3, mock_openai_client):
     task = "A" * 2048  # Input longer than API's limit
     expected_error_message = "Error running Dalle3: API Error"
     mock_openai_client.images.generate.side_effect = OpenAIError(
-        expected_error_message, http_status=500, error="Internal Server Error"
+        expected_error_message,
+        http_status=500,
+        error="Internal Server Error",
     )
 
     # Act and assert
@@ -186,7 +194,9 @@ def test_dalle3_call_with_large_input(dalle3, mock_openai_client):
     assert str(excinfo.value) == expected_error_message
 
 
-def test_dalle3_create_variations_with_invalid_image_url(dalle3, mock_openai_client):
+def test_dalle3_create_variations_with_invalid_image_url(
+    dalle3, mock_openai_client
+):
     # Arrange
     img_url = "https://invalid-image-url.com"
     expected_error_message = "Error running Dalle3: Invalid image URL"
@@ -222,13 +232,15 @@ def test_dalle3_convert_to_bytesio_invalid_format(dalle3):
 def test_dalle3_call_with_retry(dalle3, mock_openai_client):
     # Arrange
     task = "A painting of a dog"
-    expected_img_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    )
+    expected_img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
 
     # Simulate a retry scenario
     mock_openai_client.images.generate.side_effect = [
-        OpenAIError("Temporary error", http_status=500, error="Internal Server Error"),
+        OpenAIError(
+            "Temporary error",
+            http_status=500,
+            error="Internal Server Error",
+        ),
         Mock(data=[Mock(url=expected_img_url)]),
     ]
 
@@ -240,16 +252,20 @@ def test_dalle3_call_with_retry(dalle3, mock_openai_client):
     assert mock_openai_client.images.generate.call_count == 2
 
 
-def test_dalle3_create_variations_with_retry(dalle3, mock_openai_client):
+def test_dalle3_create_variations_with_retry(
+    dalle3, mock_openai_client
+):
     # Arrange
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    expected_variation_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_02ABCDE.png"
-    )
+    expected_variation_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_02ABCDE.png"
 
     # Simulate a retry scenario
     mock_openai_client.images.create_variation.side_effect = [
-        OpenAIError("Temporary error", http_status=500, error="Internal Server Error"),
+        OpenAIError(
+            "Temporary error",
+            http_status=500,
+            error="Internal Server Error",
+        ),
         Mock(data=[Mock(url=expected_variation_url)]),
     ]
 
@@ -261,14 +277,18 @@ def test_dalle3_create_variations_with_retry(dalle3, mock_openai_client):
     assert mock_openai_client.images.create_variation.call_count == 2
 
 
-def test_dalle3_call_exception_logging(dalle3, mock_openai_client, capsys):
+def test_dalle3_call_exception_logging(
+    dalle3, mock_openai_client, capsys
+):
     # Arrange
     task = "A painting of a dog"
     expected_error_message = "Error running Dalle3: API Error"
 
     # Mocking OpenAIError
     mock_openai_client.images.generate.side_effect = OpenAIError(
-        expected_error_message, http_status=500, error="Internal Server Error"
+        expected_error_message,
+        http_status=500,
+        error="Internal Server Error",
     )
 
     # Act
@@ -280,14 +300,20 @@ def test_dalle3_call_exception_logging(dalle3, mock_openai_client, capsys):
     assert expected_error_message in captured.err
 
 
-def test_dalle3_create_variations_exception_logging(dalle3, mock_openai_client, capsys):
+def test_dalle3_create_variations_exception_logging(
+    dalle3, mock_openai_client, capsys
+):
     # Arrange
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
     expected_error_message = "Error running Dalle3: API Error"
 
     # Mocking OpenAIError
-    mock_openai_client.images.create_variation.side_effect = OpenAIError(
-        expected_error_message, http_status=500, error="Internal Server Error"
+    mock_openai_client.images.create_variation.side_effect = (
+        OpenAIError(
+            expected_error_message,
+            http_status=500,
+            error="Internal Server Error",
+        )
     )
 
     # Act
@@ -312,7 +338,9 @@ def test_dalle3_call_no_api_key():
     # Arrange
     task = "A painting of a dog"
     dalle3 = Dalle3(api_key=None)
-    expected_error_message = "Error running Dalle3: API Key is missing"
+    expected_error_message = (
+        "Error running Dalle3: API Key is missing"
+    )
 
     # Act and assert
     with pytest.raises(ValueError) as excinfo:
@@ -325,7 +353,9 @@ def test_dalle3_create_variations_no_api_key():
     # Arrange
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
     dalle3 = Dalle3(api_key=None)
-    expected_error_message = "Error running Dalle3: API Key is missing"
+    expected_error_message = (
+        "Error running Dalle3: API Key is missing"
+    )
 
     # Act and assert
     with pytest.raises(ValueError) as excinfo:
@@ -334,13 +364,17 @@ def test_dalle3_create_variations_no_api_key():
     assert str(excinfo.value) == expected_error_message
 
 
-def test_dalle3_call_with_retry_max_retries_exceeded(dalle3, mock_openai_client):
+def test_dalle3_call_with_retry_max_retries_exceeded(
+    dalle3, mock_openai_client
+):
     # Arrange
     task = "A painting of a dog"
 
     # Simulate max retries exceeded
     mock_openai_client.images.generate.side_effect = OpenAIError(
-        "Temporary error", http_status=500, error="Internal Server Error"
+        "Temporary error",
+        http_status=500,
+        error="Internal Server Error",
     )
 
     # Act and assert
@@ -357,8 +391,12 @@ def test_dalle3_create_variations_with_retry_max_retries_exceeded(
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
 
     # Simulate max retries exceeded
-    mock_openai_client.images.create_variation.side_effect = OpenAIError(
-        "Temporary error", http_status=500, error="Internal Server Error"
+    mock_openai_client.images.create_variation.side_effect = (
+        OpenAIError(
+            "Temporary error",
+            http_status=500,
+            error="Internal Server Error",
+        )
     )
 
     # Act and assert
@@ -371,13 +409,15 @@ def test_dalle3_create_variations_with_retry_max_retries_exceeded(
 def test_dalle3_call_retry_with_success(dalle3, mock_openai_client):
     # Arrange
     task = "A painting of a dog"
-    expected_img_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    )
+    expected_img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
 
     # Simulate success after a retry
     mock_openai_client.images.generate.side_effect = [
-        OpenAIError("Temporary error", http_status=500, error="Internal Server Error"),
+        OpenAIError(
+            "Temporary error",
+            http_status=500,
+            error="Internal Server Error",
+        ),
         Mock(data=[Mock(url=expected_img_url)]),
     ]
 
@@ -389,16 +429,20 @@ def test_dalle3_call_retry_with_success(dalle3, mock_openai_client):
     assert mock_openai_client.images.generate.call_count == 2
 
 
-def test_dalle3_create_variations_retry_with_success(dalle3, mock_openai_client):
+def test_dalle3_create_variations_retry_with_success(
+    dalle3, mock_openai_client
+):
     # Arrange
     img_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_01J9J5ZKJZJY9.png"
-    expected_variation_url = (
-        "https://cdn.openai.com/dall-e/encoded/feats/feats_02ABCDE.png"
-    )
+    expected_variation_url = "https://cdn.openai.com/dall-e/encoded/feats/feats_02ABCDE.png"
 
     # Simulate success after a retry
     mock_openai_client.images.create_variation.side_effect = [
-        OpenAIError("Temporary error", http_status=500, error="Internal Server Error"),
+        OpenAIError(
+            "Temporary error",
+            http_status=500,
+            error="Internal Server Error",
+        ),
         Mock(data=[Mock(url=expected_variation_url)]),
     ]
 
diff --git a/tests/models/distill_whisper.py b/tests/models/test_distill_whisper.py
similarity index 67%
rename from tests/models/distill_whisper.py
rename to tests/models/test_distill_whisper.py
index d83caf62..775bb896 100644
--- a/tests/models/distill_whisper.py
+++ b/tests/models/test_distill_whisper.py
@@ -8,7 +8,10 @@ import pytest
 import torch
 from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor
 
-from swarms.models.distilled_whisperx import DistilWhisperModel, async_retry
+from swarms.models.distilled_whisperx import (
+    DistilWhisperModel,
+    async_retry,
+)
 
 
 @pytest.fixture
@@ -16,7 +19,9 @@ def distil_whisper_model():
     return DistilWhisperModel()
 
 
-def create_audio_file(data: np.ndarray, sample_rate: int, file_path: str):
+def create_audio_file(
+    data: np.ndarray, sample_rate: int, file_path: str
+):
     data.tofile(file_path)
     return file_path
 
@@ -29,10 +34,18 @@ def test_initialization(distil_whisper_model):
 
 
 def test_transcribe_audio_file(distil_whisper_model):
-    test_data = np.random.rand(16000)  # Simulated audio data (1 second)
-    with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as audio_file:
-        audio_file_path = create_audio_file(test_data, 16000, audio_file.name)
-        transcription = distil_whisper_model.transcribe(audio_file_path)
+    test_data = np.random.rand(
+        16000
+    )  # Simulated audio data (1 second)
+    with tempfile.NamedTemporaryFile(
+        suffix=".wav", delete=False
+    ) as audio_file:
+        audio_file_path = create_audio_file(
+            test_data, 16000, audio_file.name
+        )
+        transcription = distil_whisper_model.transcribe(
+            audio_file_path
+        )
         os.remove(audio_file_path)
 
     assert isinstance(transcription, str)
@@ -41,10 +54,18 @@ def test_transcribe_audio_file(distil_whisper_model):
 
 @pytest.mark.asyncio
 async def test_async_transcribe_audio_file(distil_whisper_model):
-    test_data = np.random.rand(16000)  # Simulated audio data (1 second)
-    with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as audio_file:
-        audio_file_path = create_audio_file(test_data, 16000, audio_file.name)
-        transcription = await distil_whisper_model.async_transcribe(audio_file_path)
+    test_data = np.random.rand(
+        16000
+    )  # Simulated audio data (1 second)
+    with tempfile.NamedTemporaryFile(
+        suffix=".wav", delete=False
+    ) as audio_file:
+        audio_file_path = create_audio_file(
+            test_data, 16000, audio_file.name
+        )
+        transcription = await distil_whisper_model.async_transcribe(
+            audio_file_path
+        )
         os.remove(audio_file_path)
 
     assert isinstance(transcription, str)
@@ -52,8 +73,12 @@ async def test_async_transcribe_audio_file(distil_whisper_model):
 
 
 def test_transcribe_audio_data(distil_whisper_model):
-    test_data = np.random.rand(16000)  # Simulated audio data (1 second)
-    transcription = distil_whisper_model.transcribe(test_data.tobytes())
+    test_data = np.random.rand(
+        16000
+    )  # Simulated audio data (1 second)
+    transcription = distil_whisper_model.transcribe(
+        test_data.tobytes()
+    )
 
     assert isinstance(transcription, str)
     assert transcription.strip() != ""
@@ -61,19 +86,31 @@ def test_transcribe_audio_data(distil_whisper_model):
 
 @pytest.mark.asyncio
 async def test_async_transcribe_audio_data(distil_whisper_model):
-    test_data = np.random.rand(16000)  # Simulated audio data (1 second)
-    transcription = await distil_whisper_model.async_transcribe(test_data.tobytes())
+    test_data = np.random.rand(
+        16000
+    )  # Simulated audio data (1 second)
+    transcription = await distil_whisper_model.async_transcribe(
+        test_data.tobytes()
+    )
 
     assert isinstance(transcription, str)
     assert transcription.strip() != ""
 
 
 def test_real_time_transcribe(distil_whisper_model, capsys):
-    test_data = np.random.rand(16000 * 5)  # Simulated audio data (5 seconds)
-    with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as audio_file:
-        audio_file_path = create_audio_file(test_data, 16000, audio_file.name)
-
-        distil_whisper_model.real_time_transcribe(audio_file_path, chunk_duration=1)
+    test_data = np.random.rand(
+        16000 * 5
+    )  # Simulated audio data (5 seconds)
+    with tempfile.NamedTemporaryFile(
+        suffix=".wav", delete=False
+    ) as audio_file:
+        audio_file_path = create_audio_file(
+            test_data, 16000, audio_file.name
+        )
+
+        distil_whisper_model.real_time_transcribe(
+            audio_file_path, chunk_duration=1
+        )
 
         os.remove(audio_file_path)
 
@@ -82,9 +119,13 @@ def test_real_time_transcribe(distil_whisper_model, capsys):
     assert "Chunk" in captured.out
 
 
-def test_real_time_transcribe_audio_file_not_found(distil_whisper_model, capsys):
+def test_real_time_transcribe_audio_file_not_found(
+    distil_whisper_model, capsys
+):
     audio_file_path = "non_existent_audio.wav"
-    distil_whisper_model.real_time_transcribe(audio_file_path, chunk_duration=1)
+    distil_whisper_model.real_time_transcribe(
+        audio_file_path, chunk_duration=1
+    )
 
     captured = capsys.readouterr()
     assert "The audio file was not found." in captured.out
@@ -92,7 +133,9 @@ def test_real_time_transcribe_audio_file_not_found(distil_whisper_model, capsys)
 
 @pytest.fixture
 def mock_async_retry():
-    def _mock_async_retry(retries=3, exceptions=(Exception,), delay=1):
+    def _mock_async_retry(
+        retries=3, exceptions=(Exception,), delay=1
+    ):
         def decorator(func):
             @wraps(func)
             async def wrapper(*args, **kwargs):
@@ -102,7 +145,9 @@ def mock_async_retry():
 
         return decorator
 
-    with patch("distil_whisper_model.async_retry", new=_mock_async_retry()):
+    with patch(
+        "distil_whisper_model.async_retry", new=_mock_async_retry()
+    ):
         yield
 
 
@@ -136,16 +181,24 @@ async def test_async_retry_decorator_multiple_attempts():
             return "Success"
 
     mock_async_function.attempts = 0
-    decorated_function = async_retry(max_retries=2)(mock_async_function)
+    decorated_function = async_retry(max_retries=2)(
+        mock_async_function
+    )
     result = await decorated_function()
     assert result == "Success"
 
 
 def test_create_audio_file():
-    test_data = np.random.rand(16000)  # Simulated audio data (1 second)
+    test_data = np.random.rand(
+        16000
+    )  # Simulated audio data (1 second)
     sample_rate = 16000
-    with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as audio_file:
-        audio_file_path = create_audio_file(test_data, sample_rate, audio_file.name)
+    with tempfile.NamedTemporaryFile(
+        suffix=".wav", delete=False
+    ) as audio_file:
+        audio_file_path = create_audio_file(
+            test_data, sample_rate, audio_file.name
+        )
 
         assert os.path.exists(audio_file_path)
         os.remove(audio_file_path)
@@ -209,20 +262,30 @@ def test_file_not_found(whisper_model, invalid_audio_file_path):
 
 # Asynchronous tests
 @pytest.mark.asyncio
-async def test_async_transcription_success(whisper_model, audio_file_path):
-    transcription = await whisper_model.async_transcribe(audio_file_path)
+async def test_async_transcription_success(
+    whisper_model, audio_file_path
+):
+    transcription = await whisper_model.async_transcribe(
+        audio_file_path
+    )
     assert isinstance(transcription, str)
 
 
 @pytest.mark.asyncio
-async def test_async_transcription_failure(whisper_model, invalid_audio_file_path):
+async def test_async_transcription_failure(
+    whisper_model, invalid_audio_file_path
+):
     with pytest.raises(Exception):
         await whisper_model.async_transcribe(invalid_audio_file_path)
 
 
 # Testing real-time transcription simulation
-def test_real_time_transcription(whisper_model, audio_file_path, capsys):
-    whisper_model.real_time_transcribe(audio_file_path, chunk_duration=1)
+def test_real_time_transcription(
+    whisper_model, audio_file_path, capsys
+):
+    whisper_model.real_time_transcribe(
+        audio_file_path, chunk_duration=1
+    )
     captured = capsys.readouterr()
     assert "Starting real-time transcription..." in captured.out
 
@@ -248,17 +311,26 @@ def mocked_model(monkeypatch):
         model_mock,
     )
     monkeypatch.setattr(
-        "swarms.models.distilled_whisperx.AutoProcessor.from_pretrained", processor_mock
+        "swarms.models.distilled_whisperx.AutoProcessor.from_pretrained",
+        processor_mock,
     )
     return model_mock, processor_mock
 
 
 @pytest.mark.asyncio
-async def test_async_transcribe_with_mocked_model(mocked_model, audio_file_path):
+async def test_async_transcribe_with_mocked_model(
+    mocked_model, audio_file_path
+):
     model_mock, processor_mock = mocked_model
     # Set up what the mock should return when it's called
-    model_mock.return_value.generate.return_value = torch.tensor([[0]])
-    processor_mock.return_value.batch_decode.return_value = ["mocked transcription"]
+    model_mock.return_value.generate.return_value = torch.tensor(
+        [[0]]
+    )
+    processor_mock.return_value.batch_decode.return_value = [
+        "mocked transcription"
+    ]
     model_wrapper = DistilWhisperModel()
-    transcription = await model_wrapper.async_transcribe(audio_file_path)
+    transcription = await model_wrapper.async_transcribe(
+        audio_file_path
+    )
     assert transcription == "mocked transcription"
diff --git a/tests/models/distilled_whisperx.py b/tests/models/test_distilled_whisperx.py
similarity index 100%
rename from tests/models/distilled_whisperx.py
rename to tests/models/test_distilled_whisperx.py
diff --git a/tests/models/elevenlab.py b/tests/models/test_elevenlab.py
similarity index 66%
rename from tests/models/elevenlab.py
rename to tests/models/test_elevenlab.py
index 7dbcf2ea..b28ecb31 100644
--- a/tests/models/elevenlab.py
+++ b/tests/models/test_elevenlab.py
@@ -1,6 +1,9 @@
 import pytest
 from unittest.mock import patch, mock_open
-from swarms.models.eleven_labs import ElevenLabsText2SpeechTool, ElevenLabsModel
+from swarms.models.eleven_labs import (
+    ElevenLabsText2SpeechTool,
+    ElevenLabsModel,
+)
 import os
 from dotenv import load_dotenv
 
@@ -26,31 +29,45 @@ def test_run_text_to_speech(eleven_labs_tool):
 
 
 def test_play_speech(eleven_labs_tool):
-    with patch("builtins.open", mock_open(read_data="fake_audio_data")):
+    with patch(
+        "builtins.open", mock_open(read_data="fake_audio_data")
+    ):
         eleven_labs_tool.play(EXPECTED_SPEECH_FILE)
 
 
 def test_stream_speech(eleven_labs_tool):
-    with patch("tempfile.NamedTemporaryFile", mock_open()) as mock_file:
+    with patch(
+        "tempfile.NamedTemporaryFile", mock_open()
+    ) as mock_file:
         eleven_labs_tool.stream_speech(SAMPLE_TEXT)
-        mock_file.assert_called_with(mode="bx", suffix=".wav", delete=False)
+        mock_file.assert_called_with(
+            mode="bx", suffix=".wav", delete=False
+        )
 
 
 # Testing fixture and environment variables
 def test_api_key_validation(eleven_labs_tool):
-    with patch("langchain.utils.get_from_dict_or_env", return_value=API_KEY):
+    with patch(
+        "langchain.utils.get_from_dict_or_env", return_value=API_KEY
+    ):
         values = {"eleven_api_key": None}
-        validated_values = eleven_labs_tool.validate_environment(values)
+        validated_values = eleven_labs_tool.validate_environment(
+            values
+        )
         assert "eleven_api_key" in validated_values
 
 
 # Mocking the external library
 def test_run_text_to_speech_with_mock(eleven_labs_tool):
-    with patch("tempfile.NamedTemporaryFile", mock_open()) as mock_file, patch(
+    with patch(
+        "tempfile.NamedTemporaryFile", mock_open()
+    ) as mock_file, patch(
         "your_module._import_elevenlabs"
     ) as mock_elevenlabs:
         mock_elevenlabs_instance = mock_elevenlabs.return_value
-        mock_elevenlabs_instance.generate.return_value = b"fake_audio_data"
+        mock_elevenlabs_instance.generate.return_value = (
+            b"fake_audio_data"
+        )
         eleven_labs_tool.run(SAMPLE_TEXT)
         assert mock_file.call_args[1]["suffix"] == ".wav"
         assert mock_file.call_args[1]["delete"] is False
@@ -61,19 +78,27 @@ def test_run_text_to_speech_with_mock(eleven_labs_tool):
 def test_run_text_to_speech_error_handling(eleven_labs_tool):
     with patch("your_module._import_elevenlabs") as mock_elevenlabs:
         mock_elevenlabs_instance = mock_elevenlabs.return_value
-        mock_elevenlabs_instance.generate.side_effect = Exception("Test Exception")
+        mock_elevenlabs_instance.generate.side_effect = Exception(
+            "Test Exception"
+        )
         with pytest.raises(
             RuntimeError,
-            match="Error while running ElevenLabsText2SpeechTool: Test Exception",
+            match=(
+                "Error while running ElevenLabsText2SpeechTool: Test"
+                " Exception"
+            ),
         ):
             eleven_labs_tool.run(SAMPLE_TEXT)
 
 
 # Parameterized testing
 @pytest.mark.parametrize(
-    "model", [ElevenLabsModel.MULTI_LINGUAL, ElevenLabsModel.MONO_LINGUAL]
+    "model",
+    [ElevenLabsModel.MULTI_LINGUAL, ElevenLabsModel.MONO_LINGUAL],
 )
-def test_run_text_to_speech_with_different_models(eleven_labs_tool, model):
+def test_run_text_to_speech_with_different_models(
+    eleven_labs_tool, model
+):
     eleven_labs_tool.model = model
     speech_file = eleven_labs_tool.run(SAMPLE_TEXT)
     assert isinstance(speech_file, str)
diff --git a/tests/models/fuyu.py b/tests/models/test_fuyu.py
similarity index 92%
rename from tests/models/fuyu.py
rename to tests/models/test_fuyu.py
index 9a26dbfb..0fc74035 100644
--- a/tests/models/fuyu.py
+++ b/tests/models/test_fuyu.py
@@ -36,7 +36,9 @@ def fuyu_instance():
 # Test using the fixture.
 def test_fuyu_processor_initialization(fuyu_instance):
     assert isinstance(fuyu_instance.processor, FuyuProcessor)
-    assert isinstance(fuyu_instance.image_processor, FuyuImageProcessor)
+    assert isinstance(
+        fuyu_instance.image_processor, FuyuImageProcessor
+    )
 
 
 # Test exception when providing an invalid image path.
@@ -75,8 +77,13 @@ def test_tokenizer_type(fuyu_instance):
 
 
 def test_processor_has_image_processor_and_tokenizer(fuyu_instance):
-    assert fuyu_instance.processor.image_processor == fuyu_instance.image_processor
-    assert fuyu_instance.processor.tokenizer == fuyu_instance.tokenizer
+    assert (
+        fuyu_instance.processor.image_processor
+        == fuyu_instance.image_processor
+    )
+    assert (
+        fuyu_instance.processor.tokenizer == fuyu_instance.tokenizer
+    )
 
 
 def test_model_device_map(fuyu_instance):
diff --git a/tests/models/test_gpt4_vision_api.py b/tests/models/test_gpt4_vision_api.py
new file mode 100644
index 00000000..14d53f74
--- /dev/null
+++ b/tests/models/test_gpt4_vision_api.py
@@ -0,0 +1,270 @@
+import asyncio
+import os
+from unittest.mock import AsyncMock, Mock, mock_open, patch
+from aiohttp import ClientResponseError
+import pytest
+from dotenv import load_dotenv
+from requests.exceptions import RequestException
+
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+
+load_dotenv()
+
+
+custom_api_key = os.environ.get("OPENAI_API_KEY")
+img = "images/swarms.jpeg"
+
+
+@pytest.fixture
+def vision_api():
+    return GPT4VisionAPI(openai_api_key="test_api_key")
+
+
+def test_init(vision_api):
+    assert vision_api.openai_api_key == "test_api_key"
+
+
+def test_encode_image(vision_api):
+    with patch(
+        "builtins.open",
+        mock_open(read_data=b"test_image_data"),
+        create=True,
+    ):
+        encoded_image = vision_api.encode_image(img)
+        assert encoded_image == "dGVzdF9pbWFnZV9kYXRh"
+
+
+def test_run_success(vision_api):
+    expected_response = {
+        "This is the model's response."
+    }
+    with patch(
+        "requests.post",
+        return_value=Mock(json=lambda: expected_response),
+    ) as mock_post:
+        result = vision_api.run("What is this?", img)
+        mock_post.assert_called_once()
+        assert result == "This is the model's response."
+
+
+def test_run_request_error(vision_api):
+    with patch(
+        "requests.post", side_effect=RequestException("Request Error")
+    ) as mock_post:
+        with pytest.raises(RequestException):
+            vision_api.run("What is this?", img)
+
+
+def test_run_response_error(vision_api):
+    expected_response = {"error": "Model Error"}
+    with patch(
+        "requests.post",
+        return_value=Mock(json=lambda: expected_response),
+    ) as mock_post:
+        with pytest.raises(RuntimeError):
+            vision_api.run("What is this?", img)
+
+
+def test_call(vision_api):
+    expected_response = {
+        "choices": [{"text": "This is the model's response."}]
+    }
+    with patch(
+        "requests.post",
+        return_value=Mock(json=lambda: expected_response),
+    ) as mock_post:
+        result = vision_api("What is this?", img)
+        mock_post.assert_called_once()
+        assert result == "This is the model's response."
+
+
+@pytest.fixture
+def gpt_api():
+    return GPT4VisionAPI()
+
+
+def test_initialization_with_default_key():
+    api = GPT4VisionAPI()
+    assert api.openai_api_key == custom_api_key
+
+
+def test_initialization_with_custom_key():
+    custom_key = custom_api_key
+    api = GPT4VisionAPI(openai_api_key=custom_key)
+    assert api.openai_api_key == custom_key
+
+
+def test_run_successful_response(gpt_api):
+    task = "What is in the image?"
+    img_url = img
+    response_json = {
+        "choices": [{"text": "Answer from GPT-4 Vision"}]
+    }
+    mock_response = Mock()
+    mock_response.json.return_value = response_json
+    with patch(
+        "requests.post", return_value=mock_response
+    ) as mock_post:
+        result = gpt_api.run(task, img_url)
+        mock_post.assert_called_once()
+    assert result == response_json["choices"][0]["text"]
+
+
+def test_run_with_exception(gpt_api):
+    task = "What is in the image?"
+    img_url = img
+    with patch(
+        "requests.post", side_effect=Exception("Test Exception")
+    ):
+        with pytest.raises(Exception):
+            gpt_api.run(task, img_url)
+
+
+def test_call_method_successful_response(gpt_api):
+    task = "What is in the image?"
+    img_url = img
+    response_json = {
+        "choices": [{"text": "Answer from GPT-4 Vision"}]
+    }
+    mock_response = Mock()
+    mock_response.json.return_value = response_json
+    with patch(
+        "requests.post", return_value=mock_response
+    ) as mock_post:
+        result = gpt_api(task, img_url)
+        mock_post.assert_called_once()
+    assert result == response_json
+
+
+def test_call_method_with_exception(gpt_api):
+    task = "What is in the image?"
+    img_url = img
+    with patch(
+        "requests.post", side_effect=Exception("Test Exception")
+    ):
+        with pytest.raises(Exception):
+            gpt_api(task, img_url)
+
+
+@pytest.mark.asyncio
+async def test_arun_success(vision_api):
+    expected_response = {
+        "choices": [
+            {"message": {"content": "This is the model's response."}}
+        ]
+    }
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        return_value=AsyncMock(
+            json=AsyncMock(return_value=expected_response)
+        ),
+    ) as mock_post:
+        result = await vision_api.arun("What is this?", img)
+        mock_post.assert_called_once()
+        assert result == "This is the model's response."
+
+
+@pytest.mark.asyncio
+async def test_arun_request_error(vision_api):
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        side_effect=Exception("Request Error"),
+    ) as mock_post:
+        with pytest.raises(Exception):
+            await vision_api.arun("What is this?", img)
+
+
+def test_run_many_success(vision_api):
+    expected_response = {
+        "choices": [
+            {"message": {"content": "This is the model's response."}}
+        ]
+    }
+    with patch(
+        "requests.post",
+        return_value=Mock(json=lambda: expected_response),
+    ) as mock_post:
+        tasks = ["What is this?", "What is that?"]
+        imgs = [img, img]
+        results = vision_api.run_many(tasks, imgs)
+        assert mock_post.call_count == 2
+        assert results == [
+            "This is the model's response.",
+            "This is the model's response.",
+        ]
+
+
+def test_run_many_request_error(vision_api):
+    with patch(
+        "requests.post", side_effect=RequestException("Request Error")
+    ) as mock_post:
+        tasks = ["What is this?", "What is that?"]
+        imgs = [img, img]
+        with pytest.raises(RequestException):
+            vision_api.run_many(tasks, imgs)
+
+
+@pytest.mark.asyncio
+async def test_arun_json_decode_error(vision_api):
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        return_value=AsyncMock(
+            json=AsyncMock(side_effect=ValueError)
+        ),
+    ) as mock_post:
+        with pytest.raises(ValueError):
+            await vision_api.arun("What is this?", img)
+
+
+@pytest.mark.asyncio
+async def test_arun_api_error(vision_api):
+    error_response = {"error": {"message": "API Error"}}
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        return_value=AsyncMock(
+            json=AsyncMock(return_value=error_response)
+        ),
+    ) as mock_post:
+        with pytest.raises(Exception, match="API Error"):
+            await vision_api.arun("What is this?", img)
+
+
+@pytest.mark.asyncio
+async def test_arun_unexpected_response(vision_api):
+    unexpected_response = {"unexpected": "response"}
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        return_value=AsyncMock(
+            json=AsyncMock(return_value=unexpected_response)
+        ),
+    ) as mock_post:
+        with pytest.raises(Exception, match="Unexpected response"):
+            await vision_api.arun("What is this?", img)
+
+
+@pytest.mark.asyncio
+async def test_arun_retries(vision_api):
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        side_effect=ClientResponseError(None, None),
+    ) as mock_post:
+        with pytest.raises(ClientResponseError):
+            await vision_api.arun("What is this?", img)
+        assert mock_post.call_count == vision_api.retries + 1
+
+
+@pytest.mark.asyncio
+async def test_arun_timeout(vision_api):
+    with patch(
+        "aiohttp.ClientSession.post",
+        new_callable=AsyncMock,
+        side_effect=asyncio.TimeoutError,
+    ) as mock_post:
+        with pytest.raises(asyncio.TimeoutError):
+            await vision_api.arun("What is this?", img)
diff --git a/tests/models/gpt4v.py b/tests/models/test_gpt4v.py
similarity index 83%
rename from tests/models/gpt4v.py
rename to tests/models/test_gpt4v.py
index 23e97d03..cd0ee6d5 100644
--- a/tests/models/gpt4v.py
+++ b/tests/models/test_gpt4v.py
@@ -4,7 +4,12 @@ from unittest.mock import Mock
 
 import pytest
 from dotenv import load_dotenv
-from requests.exceptions import ConnectionError, HTTPError, RequestException, Timeout
+from requests.exceptions import (
+    ConnectionError,
+    HTTPError,
+    RequestException,
+    Timeout,
+)
 
 from swarms.models.gpt4v import GPT4Vision, GPT4VisionResponse
 
@@ -99,7 +104,9 @@ def test_gpt4vision_process_img_nonexistent_file():
         gpt4vision.process_img(img_path)
 
 
-def test_gpt4vision_call_single_task_single_image_no_openai_client(gpt4vision):
+def test_gpt4vision_call_single_task_single_image_no_openai_client(
+    gpt4vision,
+):
     # Arrange
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
@@ -116,7 +123,9 @@ def test_gpt4vision_call_single_task_single_image_empty_response(
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
 
-    mock_openai_client.chat.completions.create.return_value.choices = []
+    mock_openai_client.chat.completions.create.return_value.choices = (
+        []
+    )
 
     # Act
     response = gpt4vision(img_url, [task])
@@ -133,7 +142,9 @@ def test_gpt4vision_call_multiple_tasks_single_image_empty_responses(
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     tasks = ["Describe this image.", "What's in this picture?"]
 
-    mock_openai_client.chat.completions.create.return_value.choices = []
+    mock_openai_client.chat.completions.create.return_value.choices = (
+        []
+    )
 
     # Act
     responses = gpt4vision(img_url, tasks)
@@ -173,7 +184,13 @@ def test_gpt4vision_call_retry_with_success_after_timeout(
         Timeout("Request timed out"),
         {
             "choices": [
-                {"message": {"content": {"text": "A description of the image."}}}
+                {
+                    "message": {
+                        "content": {
+                            "text": "A description of the image."
+                        }
+                    }
+                }
             ],
         },
     ]
@@ -200,12 +217,16 @@ def test_gpt4vision_process_img():
     assert img_data.startswith("/9j/")  # Base64-encoded image data
 
 
-def test_gpt4vision_call_single_task_single_image(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_single_task_single_image(
+    gpt4vision, mock_openai_client
+):
     # Arrange
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
 
-    expected_response = GPT4VisionResponse(answer="A description of the image.")
+    expected_response = GPT4VisionResponse(
+        answer="A description of the image."
+    )
 
     mock_openai_client.chat.completions.create.return_value.choices[
         0
@@ -219,12 +240,19 @@ def test_gpt4vision_call_single_task_single_image(gpt4vision, mock_openai_client
     mock_openai_client.chat.completions.create.assert_called_once()
 
 
-def test_gpt4vision_call_single_task_multiple_images(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_single_task_multiple_images(
+    gpt4vision, mock_openai_client
+):
     # Arrange
-    img_urls = ["https://example.com/image1.jpg", "https://example.com/image2.jpg"]
+    img_urls = [
+        "https://example.com/image1.jpg",
+        "https://example.com/image2.jpg",
+    ]
     task = "Describe these images."
 
-    expected_response = GPT4VisionResponse(answer="Descriptions of the images.")
+    expected_response = GPT4VisionResponse(
+        answer="Descriptions of the images."
+    )
 
     mock_openai_client.chat.completions.create.return_value.choices[
         0
@@ -238,7 +266,9 @@ def test_gpt4vision_call_single_task_multiple_images(gpt4vision, mock_openai_cli
     mock_openai_client.chat.completions.create.assert_called_once()
 
 
-def test_gpt4vision_call_multiple_tasks_single_image(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_multiple_tasks_single_image(
+    gpt4vision, mock_openai_client
+):
     # Arrange
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     tasks = ["Describe this image.", "What's in this picture?"]
@@ -249,10 +279,15 @@ def test_gpt4vision_call_multiple_tasks_single_image(gpt4vision, mock_openai_cli
     ]
 
     def create_mock_response(response):
-        return {"choices": [{"message": {"content": {"text": response.answer}}}]}
+        return {
+            "choices": [
+                {"message": {"content": {"text": response.answer}}}
+            ]
+        }
 
     mock_openai_client.chat.completions.create.side_effect = [
-        create_mock_response(response) for response in expected_responses
+        create_mock_response(response)
+        for response in expected_responses
     ]
 
     # Act
@@ -279,7 +314,13 @@ def test_gpt4vision_call_multiple_tasks_single_image(gpt4vision, mock_openai_cli
         mock_openai_client.chat.completions.create.side_effect = [
             {
                 "choices": [
-                    {"message": {"content": {"text": expected_responses[i].answer}}}
+                    {
+                        "message": {
+                            "content": {
+                                "text": expected_responses[i].answer
+                            }
+                        }
+                    }
                 ]
             }
             for i in range(len(expected_responses))
@@ -295,7 +336,9 @@ def test_gpt4vision_call_multiple_tasks_single_image(gpt4vision, mock_openai_cli
         )  # Should be called only once
 
 
-def test_gpt4vision_call_multiple_tasks_multiple_images(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_multiple_tasks_multiple_images(
+    gpt4vision, mock_openai_client
+):
     # Arrange
     img_urls = [
         "https://images.unsplash.com/photo-1694734479857-626882b6db37?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
@@ -309,7 +352,11 @@ def test_gpt4vision_call_multiple_tasks_multiple_images(gpt4vision, mock_openai_
     ]
 
     mock_openai_client.chat.completions.create.side_effect = [
-        {"choices": [{"message": {"content": {"text": response.answer}}}]}
+        {
+            "choices": [
+                {"message": {"content": {"text": response.answer}}}
+            ]
+        }
         for response in expected_responses
     ]
 
@@ -328,20 +375,24 @@ def test_gpt4vision_call_http_error(gpt4vision, mock_openai_client):
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
 
-    mock_openai_client.chat.completions.create.side_effect = HTTPError("HTTP Error")
+    mock_openai_client.chat.completions.create.side_effect = (
+        HTTPError("HTTP Error")
+    )
 
     # Act and Assert
     with pytest.raises(HTTPError):
         gpt4vision(img_url, [task])
 
 
-def test_gpt4vision_call_request_error(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_request_error(
+    gpt4vision, mock_openai_client
+):
     # Arrange
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
 
-    mock_openai_client.chat.completions.create.side_effect = RequestException(
-        "Request Error"
+    mock_openai_client.chat.completions.create.side_effect = (
+        RequestException("Request Error")
     )
 
     # Act and Assert
@@ -349,13 +400,15 @@ def test_gpt4vision_call_request_error(gpt4vision, mock_openai_client):
         gpt4vision(img_url, [task])
 
 
-def test_gpt4vision_call_connection_error(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_connection_error(
+    gpt4vision, mock_openai_client
+):
     # Arrange
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
 
-    mock_openai_client.chat.completions.create.side_effect = ConnectionError(
-        "Connection Error"
+    mock_openai_client.chat.completions.create.side_effect = (
+        ConnectionError("Connection Error")
     )
 
     # Act and Assert
@@ -363,7 +416,9 @@ def test_gpt4vision_call_connection_error(gpt4vision, mock_openai_client):
         gpt4vision(img_url, [task])
 
 
-def test_gpt4vision_call_retry_with_success(gpt4vision, mock_openai_client):
+def test_gpt4vision_call_retry_with_success(
+    gpt4vision, mock_openai_client
+):
     # Arrange
     img_url = "https://images.unsplash.com/photo-1694734479942-8cc7f4660578?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
     task = "Describe this image."
diff --git a/tests/models/hf.py b/tests/models/test_hf.py
similarity index 85%
rename from tests/models/hf.py
rename to tests/models/test_hf.py
index ab3b648d..dce13338 100644
--- a/tests/models/hf.py
+++ b/tests/models/test_hf.py
@@ -26,7 +26,10 @@ def mock_bitsandbytesconfig():
 
 @pytest.fixture
 def hugging_face_llm(
-    mock_torch, mock_autotokenizer, mock_automodelforcausallm, mock_bitsandbytesconfig
+    mock_torch,
+    mock_autotokenizer,
+    mock_automodelforcausallm,
+    mock_bitsandbytesconfig,
 ):
     HuggingFaceLLM.torch = mock_torch
     HuggingFaceLLM.AutoTokenizer = mock_autotokenizer
@@ -36,7 +39,9 @@ def hugging_face_llm(
     return HuggingFaceLLM(model_id="test")
 
 
-def test_init(hugging_face_llm, mock_autotokenizer, mock_automodelforcausallm):
+def test_init(
+    hugging_face_llm, mock_autotokenizer, mock_automodelforcausallm
+):
     assert hugging_face_llm.model_id == "test"
     mock_autotokenizer.from_pretrained.assert_called_once_with("test")
     mock_automodelforcausallm.from_pretrained.assert_called_once_with(
@@ -60,7 +65,9 @@ def test_init_with_quantize(
 
     HuggingFaceLLM(model_id="test", quantize=True)
 
-    mock_bitsandbytesconfig.assert_called_once_with(**quantization_config)
+    mock_bitsandbytesconfig.assert_called_once_with(
+        **quantization_config
+    )
     mock_autotokenizer.from_pretrained.assert_called_once_with("test")
     mock_automodelforcausallm.from_pretrained.assert_called_once_with(
         "test", quantization_config=quantization_config
@@ -70,8 +77,12 @@ def test_init_with_quantize(
 def test_generate_text(hugging_face_llm):
     prompt_text = "test prompt"
     expected_output = "test output"
-    hugging_face_llm.tokenizer.encode.return_value = torch.tensor([0])  # Mock tensor
-    hugging_face_llm.model.generate.return_value = torch.tensor([0])  # Mock tensor
+    hugging_face_llm.tokenizer.encode.return_value = torch.tensor(
+        [0]
+    )  # Mock tensor
+    hugging_face_llm.model.generate.return_value = torch.tensor(
+        [0]
+    )  # Mock tensor
     hugging_face_llm.tokenizer.decode.return_value = expected_output
 
     output = hugging_face_llm.generate_text(prompt_text)
diff --git a/tests/models/huggingface.py b/tests/models/test_huggingface.py
similarity index 78%
rename from tests/models/huggingface.py
rename to tests/models/test_huggingface.py
index 9a27054a..b313eaf4 100644
--- a/tests/models/huggingface.py
+++ b/tests/models/test_huggingface.py
@@ -11,14 +11,14 @@ from swarms.models.huggingface import (
 # Fixture for the class instance
 @pytest.fixture
 def llm_instance():
-    model_id = "gpt2-small"
+    model_id = "NousResearch/Nous-Hermes-2-Vision-Alpha"
     instance = HuggingfaceLLM(model_id=model_id)
     return instance
 
 
 # Test for instantiation and attributes
 def test_llm_initialization(llm_instance):
-    assert llm_instance.model_id == "gpt2-small"
+    assert llm_instance.model_id == "NousResearch/Nous-Hermes-2-Vision-Alpha"
     assert llm_instance.max_length == 500
     # ... add more assertions for all default attributes
 
@@ -38,7 +38,9 @@ def test_llm_bad_model_initialization():
 
 # Mocking the tokenizer and model to test run method
 @patch("swarms.models.huggingface.AutoTokenizer.from_pretrained")
-@patch("swarms.models.huggingface.AutoModelForCausalLM.from_pretrained")
+@patch(
+    "swarms.models.huggingface.AutoModelForCausalLM.from_pretrained"
+)
 def test_llm_run(mock_model, mock_tokenizer, llm_instance):
     mock_model.return_value.generate.return_value = "mocked output"
     mock_tokenizer.return_value.encode.return_value = "mocked input"
@@ -73,18 +75,22 @@ def test_llm_memory_consumption(llm_instance):
 @pytest.mark.parametrize(
     "model_id, max_length",
     [
-        ("gpt2-small", 100),
-        ("gpt2-medium", 200),
-        ("gpt2-large", None),  # None to check default behavior
+        ("NousResearch/Nous-Hermes-2-Vision-Alpha", 100),
+        ("microsoft/Orca-2-13b", 200),
+        ("berkeley-nest/Starling-LM-7B-alpha", None),  # None to check default behavior
     ],
 )
 def test_llm_initialization_params(model_id, max_length):
     if max_length:
-        instance = HuggingfaceLLM(model_id=model_id, max_length=max_length)
+        instance = HuggingfaceLLM(
+            model_id=model_id, max_length=max_length
+        )
         assert instance.max_length == max_length
     else:
         instance = HuggingfaceLLM(model_id=model_id)
-        assert instance.max_length == 500  # Assuming 500 is the default max_length
+        assert (
+            instance.max_length == 500
+        )  # Assuming 500 is the default max_length
 
 
 # Test for setting an invalid device
@@ -93,12 +99,6 @@ def test_llm_set_invalid_device(llm_instance):
         llm_instance.set_device("quantum_processor")
 
 
-# Test for model download progress bar
-@patch("swarms.models.huggingface.HuggingfaceLLM._download_model")
-def test_llm_model_download_progress(mock_download, llm_instance):
-    llm_instance.download_model_with_progress()
-    mock_download.assert_called_once()
-
 
 # Mocking external API call to test run method without network
 @patch("swarms.models.huggingface.HuggingfaceLLM.run")
@@ -139,7 +139,9 @@ def test_llm_run_output_length(mock_run, llm_instance):
 # Test the tokenizer handling special tokens correctly
 @patch("swarms.models.huggingface.HuggingfaceLLM._tokenizer.encode")
 @patch("swarms.models.huggingface.HuggingfaceLLM._tokenizer.decode")
-def test_llm_tokenizer_special_tokens(mock_decode, mock_encode, llm_instance):
+def test_llm_tokenizer_special_tokens(
+    mock_decode, mock_encode, llm_instance
+):
     mock_encode.return_value = "encoded input with special tokens"
     mock_decode.return_value = "decoded output with special tokens"
     result = llm_instance.run("test task with special tokens")
@@ -180,7 +182,8 @@ def test_llm_long_input_warning(mock_warning, llm_instance):
 
 # Test for run method behavior when model raises an exception
 @patch(
-    "swarms.models.huggingface.HuggingfaceLLM._model.generate", side_effect=RuntimeError
+    "swarms.models.huggingface.HuggingfaceLLM._model.generate",
+    side_effect=RuntimeError,
 )
 def test_llm_run_model_exception(mock_generate, llm_instance):
     with pytest.raises(RuntimeError):
@@ -189,14 +192,17 @@ def test_llm_run_model_exception(mock_generate, llm_instance):
 
 # Test the behavior when GPU is forced but not available
 @patch("torch.cuda.is_available", return_value=False)
-def test_llm_force_gpu_when_unavailable(mock_is_available, llm_instance):
+def test_llm_force_gpu_when_unavailable(
+    mock_is_available, llm_instance
+):
     with pytest.raises(EnvironmentError):
-        llm_instance.set_device("cuda")  # Attempt to set CUDA when it's not available
+        llm_instance.set_device(
+            "cuda"
+        )  # Attempt to set CUDA when it's not available
 
 
 # Test for proper cleanup after model use (releasing resources)
 @patch("swarms.models.huggingface.HuggingfaceLLM._model")
-@patch("swarms.models.huggingface.HuggingfaceLLM._tokenizer")
 def test_llm_cleanup(mock_model, mock_tokenizer, llm_instance):
     llm_instance.cleanup()
     # Assuming cleanup method is meant to free resources
@@ -204,20 +210,8 @@ def test_llm_cleanup(mock_model, mock_tokenizer, llm_instance):
     mock_tokenizer.delete.assert_called_once()
 
 
-# Test updating the configuration after instantiation
-def test_llm_update_configuration(llm_instance):
-    new_config = {"temperature": 0.7}
-    llm_instance.update_configuration(new_config)
-    assert llm_instance.configuration["temperature"] == 0.7
 
 
-# Test if the model is re-downloaded when changing the model_id
-@patch("swarms.models.huggingface.HuggingfaceLLM._download_model")
-def test_llm_change_model_id(mock_download, llm_instance):
-    new_model_id = "gpt2-xl"
-    llm_instance.model_id = new_model_id
-    mock_download.assert_called_with(new_model_id)
-
 
 # Test model's ability to handle multilingual input
 @patch("swarms.models.huggingface.HuggingfaceLLM.run")
@@ -225,7 +219,9 @@ def test_llm_multilingual_input(mock_run, llm_instance):
     mock_run.return_value = "mocked multilingual output"
     multilingual_input = "Bonjour, ceci est un test multilingue."
     result = llm_instance.run(multilingual_input)
-    assert isinstance(result, str)  # Simple check to ensure output is string type
+    assert isinstance(
+        result, str
+    )  # Simple check to ensure output is string type
 
 
 # Test caching mechanism to prevent re-running the same inputs
@@ -240,12 +236,6 @@ def test_llm_caching_mechanism(mock_run, llm_instance):
     assert first_run_result == second_run_result
 
 
-# Ensure that model re-downloads when force_download flag is set
-@patch("swarms.models.huggingface.HuggingfaceLLM._download_model")
-def test_llm_force_download(mock_download, llm_instance):
-    llm_instance.download_model_with_progress(force_download=True)
-    mock_download.assert_called_once_with(llm_instance.model_id, force=True)
-
 
 # These tests are provided as examples. In real-world scenarios, you will need to adapt these tests to the actual logic of your `HuggingfaceLLM` class.
 # For instance, "mock_model.delete.assert_called_once()" and similar lines are based on hypothetical methods and behaviors that you need to replace with actual implementations.
diff --git a/tests/models/idefics.py b/tests/models/test_idefics.py
similarity index 76%
rename from tests/models/idefics.py
rename to tests/models/test_idefics.py
index 610657bd..bb443533 100644
--- a/tests/models/idefics.py
+++ b/tests/models/test_idefics.py
@@ -1,7 +1,11 @@
 import pytest
 from unittest.mock import patch
 import torch
-from swarms.models.idefics import Idefics, IdeficsForVisionText2Text, AutoProcessor
+from swarms.models.idefics import (
+    Idefics,
+    IdeficsForVisionText2Text,
+    AutoProcessor,
+)
 
 
 @pytest.fixture
@@ -30,7 +34,8 @@ def test_init_default(idefics_instance):
 )
 def test_init_device(device, expected):
     with patch(
-        "torch.cuda.is_available", return_value=True if expected == "cuda" else False
+        "torch.cuda.is_available",
+        return_value=True if expected == "cuda" else False,
     ):
         instance = Idefics(device=device)
     assert instance.device == expected
@@ -39,10 +44,14 @@ def test_init_device(device, expected):
 # Test `run` method
 def test_run(idefics_instance):
     prompts = [["User: Test"]]
-    with patch.object(idefics_instance, "processor") as mock_processor, patch.object(
+    with patch.object(
+        idefics_instance, "processor"
+    ) as mock_processor, patch.object(
         idefics_instance, "model"
     ) as mock_model:
-        mock_processor.return_value = {"input_ids": torch.tensor([1, 2, 3])}
+        mock_processor.return_value = {
+            "input_ids": torch.tensor([1, 2, 3])
+        }
         mock_model.generate.return_value = torch.tensor([1, 2, 3])
         mock_processor.batch_decode.return_value = ["Test"]
 
@@ -54,10 +63,14 @@ def test_run(idefics_instance):
 # Test `__call__` method (using the same logic as run for simplicity)
 def test_call(idefics_instance):
     prompts = [["User: Test"]]
-    with patch.object(idefics_instance, "processor") as mock_processor, patch.object(
+    with patch.object(
+        idefics_instance, "processor"
+    ) as mock_processor, patch.object(
         idefics_instance, "model"
     ) as mock_model:
-        mock_processor.return_value = {"input_ids": torch.tensor([1, 2, 3])}
+        mock_processor.return_value = {
+            "input_ids": torch.tensor([1, 2, 3])
+        }
         mock_model.generate.return_value = torch.tensor([1, 2, 3])
         mock_processor.batch_decode.return_value = ["Test"]
 
@@ -70,7 +83,9 @@ def test_call(idefics_instance):
 def test_chat(idefics_instance):
     user_input = "User: Hello"
     response = "Model: Hi there!"
-    with patch.object(idefics_instance, "run", return_value=[response]):
+    with patch.object(
+        idefics_instance, "run", return_value=[response]
+    ):
         result = idefics_instance.chat(user_input)
 
     assert result == response
@@ -82,10 +97,14 @@ def test_set_checkpoint(idefics_instance):
     new_checkpoint = "new_checkpoint"
     with patch.object(
         IdeficsForVisionText2Text, "from_pretrained"
-    ) as mock_from_pretrained, patch.object(AutoProcessor, "from_pretrained"):
+    ) as mock_from_pretrained, patch.object(
+        AutoProcessor, "from_pretrained"
+    ):
         idefics_instance.set_checkpoint(new_checkpoint)
 
-    mock_from_pretrained.assert_called_with(new_checkpoint, torch_dtype=torch.bfloat16)
+    mock_from_pretrained.assert_called_with(
+        new_checkpoint, torch_dtype=torch.bfloat16
+    )
 
 
 # Test `set_device` method
diff --git a/tests/models/jina_embeds.py b/tests/models/test_jina_embeds.py
similarity index 100%
rename from tests/models/jina_embeds.py
rename to tests/models/test_jina_embeds.py
diff --git a/tests/models/kosmos.py b/tests/models/test_kosmos.py
similarity index 86%
rename from tests/models/kosmos.py
rename to tests/models/test_kosmos.py
index 11d224d1..1219f895 100644
--- a/tests/models/kosmos.py
+++ b/tests/models/test_kosmos.py
@@ -16,7 +16,9 @@ def mock_image_request():
     img_data = open(TEST_IMAGE_URL, "rb").read()
     mock_resp = Mock()
     mock_resp.raw = img_data
-    with patch.object(requests, "get", return_value=mock_resp) as _fixture:
+    with patch.object(
+        requests, "get", return_value=mock_resp
+    ) as _fixture:
         yield _fixture
 
 
@@ -45,7 +47,9 @@ def test_get_image(mock_image_request):
 # Test multimodal grounding
 def test_multimodal_grounding(mock_image_request):
     kosmos = Kosmos()
-    kosmos.multimodal_grounding("Find the red apple in the image.", TEST_IMAGE_URL)
+    kosmos.multimodal_grounding(
+        "Find the red apple in the image.", TEST_IMAGE_URL
+    )
     # TODO: Validate the result if possible
 
 
@@ -107,22 +111,30 @@ def kosmos():
 # Mocking the requests.get() method
 @pytest.fixture
 def mock_request_get(monkeypatch):
-    monkeypatch.setattr(requests, "get", lambda url, **kwargs: MockResponse())
+    monkeypatch.setattr(
+        requests, "get", lambda url, **kwargs: MockResponse()
+    )
 
 
 @pytest.mark.usefixtures("mock_request_get")
 def test_multimodal_grounding(kosmos):
-    kosmos.multimodal_grounding("Find the red apple in the image.", IMG_URL1)
+    kosmos.multimodal_grounding(
+        "Find the red apple in the image.", IMG_URL1
+    )
 
 
 @pytest.mark.usefixtures("mock_request_get")
 def test_referring_expression_comprehension(kosmos):
-    kosmos.referring_expression_comprehension("Show me the green bottle.", IMG_URL2)
+    kosmos.referring_expression_comprehension(
+        "Show me the green bottle.", IMG_URL2
+    )
 
 
 @pytest.mark.usefixtures("mock_request_get")
 def test_referring_expression_generation(kosmos):
-    kosmos.referring_expression_generation("It is on the table.", IMG_URL3)
+    kosmos.referring_expression_generation(
+        "It is on the table.", IMG_URL3
+    )
 
 
 @pytest.mark.usefixtures("mock_request_get")
@@ -142,12 +154,16 @@ def test_grounded_image_captioning_detailed(kosmos):
 
 @pytest.mark.usefixtures("mock_request_get")
 def test_multimodal_grounding_2(kosmos):
-    kosmos.multimodal_grounding("Find the yellow fruit in the image.", IMG_URL2)
+    kosmos.multimodal_grounding(
+        "Find the yellow fruit in the image.", IMG_URL2
+    )
 
 
 @pytest.mark.usefixtures("mock_request_get")
 def test_referring_expression_comprehension_2(kosmos):
-    kosmos.referring_expression_comprehension("Where is the water bottle?", IMG_URL3)
+    kosmos.referring_expression_comprehension(
+        "Where is the water bottle?", IMG_URL3
+    )
 
 
 @pytest.mark.usefixtures("mock_request_get")
diff --git a/tests/models/kosmos2.py b/tests/models/test_kosmos2.py
similarity index 89%
rename from tests/models/kosmos2.py
rename to tests/models/test_kosmos2.py
index 2ff01092..7e4f0e5f 100644
--- a/tests/models/kosmos2.py
+++ b/tests/models/test_kosmos2.py
@@ -36,7 +36,10 @@ def test_kosmos2_with_sample_image(kosmos2, sample_image):
 
 # Mocked extract_entities function for testing
 def mock_extract_entities(text):
-    return [("entity1", (0.1, 0.2, 0.3, 0.4)), ("entity2", (0.5, 0.6, 0.7, 0.8))]
+    return [
+        ("entity1", (0.1, 0.2, 0.3, 0.4)),
+        ("entity2", (0.5, 0.6, 0.7, 0.8)),
+    ]
 
 
 # Mocked process_entities_to_detections function for testing
@@ -52,9 +55,13 @@ def mock_process_entities_to_detections(entities, image):
 def test_kosmos2_with_mocked_extraction_and_detection(
     kosmos2, sample_image, monkeypatch
 ):
-    monkeypatch.setattr(kosmos2, "extract_entities", mock_extract_entities)
     monkeypatch.setattr(
-        kosmos2, "process_entities_to_detections", mock_process_entities_to_detections
+        kosmos2, "extract_entities", mock_extract_entities
+    )
+    monkeypatch.setattr(
+        kosmos2,
+        "process_entities_to_detections",
+        mock_process_entities_to_detections,
     )
 
     detections = kosmos2(img=sample_image)
@@ -68,7 +75,9 @@ def test_kosmos2_with_mocked_extraction_and_detection(
 
 
 # Test Kosmos2 with empty entity extraction
-def test_kosmos2_with_empty_extraction(kosmos2, sample_image, monkeypatch):
+def test_kosmos2_with_empty_extraction(
+    kosmos2, sample_image, monkeypatch
+):
     monkeypatch.setattr(kosmos2, "extract_entities", lambda x: [])
     detections = kosmos2(img=sample_image)
     assert isinstance(detections, Detections)
@@ -214,7 +223,9 @@ def test_kosmos2_with_invalid_hf_api_key(kosmos2, sample_image):
 
 
 # Test Kosmos2 with a very long generated text
-def test_kosmos2_with_long_generated_text(kosmos2, sample_image, monkeypatch):
+def test_kosmos2_with_long_generated_text(
+    kosmos2, sample_image, monkeypatch
+):
     def mock_generate_text(*args, **kwargs):
         return "A" * 10000
 
@@ -234,9 +245,16 @@ def test_kosmos2_with_entities_containing_special_characters(
     kosmos2, sample_image, monkeypatch
 ):
     def mock_extract_entities(text):
-        return [("entity1 with special characters (ΓΌ, ΓΆ, etc.)", (0.1, 0.2, 0.3, 0.4))]
+        return [
+            (
+                "entity1 with special characters (ΓΌ, ΓΆ, etc.)",
+                (0.1, 0.2, 0.3, 0.4),
+            )
+        ]
 
-    monkeypatch.setattr(kosmos2, "extract_entities", mock_extract_entities)
+    monkeypatch.setattr(
+        kosmos2, "extract_entities", mock_extract_entities
+    )
     detections = kosmos2(img=sample_image)
     assert isinstance(detections, Detections)
     assert (
@@ -252,9 +270,14 @@ def test_kosmos2_with_image_containing_multiple_objects(
     kosmos2, sample_image, monkeypatch
 ):
     def mock_extract_entities(text):
-        return [("entity1", (0.1, 0.2, 0.3, 0.4)), ("entity2", (0.5, 0.6, 0.7, 0.8))]
+        return [
+            ("entity1", (0.1, 0.2, 0.3, 0.4)),
+            ("entity2", (0.5, 0.6, 0.7, 0.8)),
+        ]
 
-    monkeypatch.setattr(kosmos2, "extract_entities", mock_extract_entities)
+    monkeypatch.setattr(
+        kosmos2, "extract_entities", mock_extract_entities
+    )
     detections = kosmos2(img=sample_image)
     assert isinstance(detections, Detections)
     assert (
@@ -266,11 +289,15 @@ def test_kosmos2_with_image_containing_multiple_objects(
 
 
 # Test Kosmos2 with image containing no objects
-def test_kosmos2_with_image_containing_no_objects(kosmos2, sample_image, monkeypatch):
+def test_kosmos2_with_image_containing_no_objects(
+    kosmos2, sample_image, monkeypatch
+):
     def mock_extract_entities(text):
         return []
 
-    monkeypatch.setattr(kosmos2, "extract_entities", mock_extract_entities)
+    monkeypatch.setattr(
+        kosmos2, "extract_entities", mock_extract_entities
+    )
     detections = kosmos2(img=sample_image)
     assert isinstance(detections, Detections)
     assert (
@@ -296,7 +323,9 @@ def test_kosmos2_with_valid_youtube_video_url(kosmos2):
 
 # Test Kosmos2 with an invalid YouTube video URL
 def test_kosmos2_with_invalid_youtube_video_url(kosmos2):
-    invalid_youtube_video_url = "https://www.youtube.com/invalid_video"
+    invalid_youtube_video_url = (
+        "https://www.youtube.com/invalid_video"
+    )
     with pytest.raises(Exception):
         kosmos2(video_url=invalid_youtube_video_url)
 
diff --git a/tests/models/llama_function_caller.py b/tests/models/test_llama_function_caller.py
similarity index 73%
rename from tests/models/llama_function_caller.py
rename to tests/models/test_llama_function_caller.py
index c54c264b..56ad481d 100644
--- a/tests/models/llama_function_caller.py
+++ b/tests/models/test_llama_function_caller.py
@@ -25,15 +25,26 @@ def test_llama_custom_function(llama_caller):
         function=sample_function,
         description="Sample custom function",
         arguments=[
-            {"name": "arg1", "type": "string", "description": "Argument 1"},
-            {"name": "arg2", "type": "string", "description": "Argument 2"},
+            {
+                "name": "arg1",
+                "type": "string",
+                "description": "Argument 1",
+            },
+            {
+                "name": "arg2",
+                "type": "string",
+                "description": "Argument 2",
+            },
         ],
     )
 
     result = llama_caller.call_function(
         "sample_function", arg1="arg1_value", arg2="arg2_value"
     )
-    assert result == "Sample function called with args: arg1_value, arg2_value"
+    assert (
+        result
+        == "Sample function called with args: arg1_value, arg2_value"
+    )
 
 
 # Test streaming user prompts
@@ -60,19 +71,31 @@ def test_llama_custom_function_invalid_arguments(llama_caller):
         function=sample_function,
         description="Sample custom function",
         arguments=[
-            {"name": "arg1", "type": "string", "description": "Argument 1"},
-            {"name": "arg2", "type": "string", "description": "Argument 2"},
+            {
+                "name": "arg1",
+                "type": "string",
+                "description": "Argument 1",
+            },
+            {
+                "name": "arg2",
+                "type": "string",
+                "description": "Argument 2",
+            },
         ],
     )
 
     with pytest.raises(TypeError):
-        llama_caller.call_function("sample_function", arg1="arg1_value")
+        llama_caller.call_function(
+            "sample_function", arg1="arg1_value"
+        )
 
 
 # Test streaming with custom runtime
 def test_llama_custom_runtime():
     llama_caller = LlamaFunctionCaller(
-        model_id="Your-Model-ID", cache_dir="Your-Cache-Directory", runtime="cuda"
+        model_id="Your-Model-ID",
+        cache_dir="Your-Cache-Directory",
+        runtime="cuda",
     )
     user_prompt = "Tell me about the tallest mountain in the world."
     response = llama_caller(user_prompt)
@@ -83,7 +106,9 @@ def test_llama_custom_runtime():
 # Test caching functionality
 def test_llama_cache():
     llama_caller = LlamaFunctionCaller(
-        model_id="Your-Model-ID", cache_dir="Your-Cache-Directory", runtime="cuda"
+        model_id="Your-Model-ID",
+        cache_dir="Your-Cache-Directory",
+        runtime="cuda",
     )
 
     # Perform a request to populate the cache
@@ -99,7 +124,9 @@ def test_llama_cache():
 # Test response length within max_tokens limit
 def test_llama_response_length():
     llama_caller = LlamaFunctionCaller(
-        model_id="Your-Model-ID", cache_dir="Your-Cache-Directory", runtime="cuda"
+        model_id="Your-Model-ID",
+        cache_dir="Your-Cache-Directory",
+        runtime="cuda",
     )
 
     # Generate a long prompt
diff --git a/tests/models/mistral.py b/tests/models/test_mistral.py
similarity index 100%
rename from tests/models/mistral.py
rename to tests/models/test_mistral.py
diff --git a/tests/models/mpt7b.py b/tests/models/test_mpt7b.py
similarity index 53%
rename from tests/models/mpt7b.py
rename to tests/models/test_mpt7b.py
index dfde578d..92b6c254 100644
--- a/tests/models/mpt7b.py
+++ b/tests/models/test_mpt7b.py
@@ -6,7 +6,9 @@ from swarms.models.mpt import MPT7B
 
 def test_mpt7b_init():
     mpt = MPT7B(
-        "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+        "mosaicml/mpt-7b-storywriter",
+        "EleutherAI/gpt-neox-20b",
+        max_tokens=150,
     )
 
     assert isinstance(mpt, MPT7B)
@@ -19,36 +21,55 @@ def test_mpt7b_init():
 
 def test_mpt7b_run():
     mpt = MPT7B(
-        "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+        "mosaicml/mpt-7b-storywriter",
+        "EleutherAI/gpt-neox-20b",
+        max_tokens=150,
+    )
+    output = mpt.run(
+        "generate", "Once upon a time in a land far, far away..."
     )
-    output = mpt.run("generate", "Once upon a time in a land far, far away...")
 
     assert isinstance(output, str)
-    assert output.startswith("Once upon a time in a land far, far away...")
+    assert output.startswith(
+        "Once upon a time in a land far, far away..."
+    )
 
 
 def test_mpt7b_run_invalid_task():
     mpt = MPT7B(
-        "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+        "mosaicml/mpt-7b-storywriter",
+        "EleutherAI/gpt-neox-20b",
+        max_tokens=150,
     )
 
     with pytest.raises(ValueError):
-        mpt.run("invalid_task", "Once upon a time in a land far, far away...")
+        mpt.run(
+            "invalid_task",
+            "Once upon a time in a land far, far away...",
+        )
 
 
 def test_mpt7b_generate():
     mpt = MPT7B(
-        "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+        "mosaicml/mpt-7b-storywriter",
+        "EleutherAI/gpt-neox-20b",
+        max_tokens=150,
+    )
+    output = mpt.generate(
+        "Once upon a time in a land far, far away..."
     )
-    output = mpt.generate("Once upon a time in a land far, far away...")
 
     assert isinstance(output, str)
-    assert output.startswith("Once upon a time in a land far, far away...")
+    assert output.startswith(
+        "Once upon a time in a land far, far away..."
+    )
 
 
 def test_mpt7b_batch_generate():
     mpt = MPT7B(
-        "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+        "mosaicml/mpt-7b-storywriter",
+        "EleutherAI/gpt-neox-20b",
+        max_tokens=150,
     )
     prompts = ["In the deep jungles,", "At the heart of the city,"]
     outputs = mpt.batch_generate(prompts, temperature=0.7)
@@ -61,7 +82,9 @@ def test_mpt7b_batch_generate():
 
 def test_mpt7b_unfreeze_model():
     mpt = MPT7B(
-        "mosaicml/mpt-7b-storywriter", "EleutherAI/gpt-neox-20b", max_tokens=150
+        "mosaicml/mpt-7b-storywriter",
+        "EleutherAI/gpt-neox-20b",
+        max_tokens=150,
     )
     mpt.unfreeze_model()
 
diff --git a/tests/models/nougat.py b/tests/models/test_nougat.py
similarity index 90%
rename from tests/models/nougat.py
rename to tests/models/test_nougat.py
index e61a45af..858845a6 100644
--- a/tests/models/nougat.py
+++ b/tests/models/test_nougat.py
@@ -21,7 +21,11 @@ def test_nougat_default_initialization(setup_nougat):
 
 
 def test_nougat_custom_initialization():
-    nougat = Nougat(model_name_or_path="custom_path", min_length=10, max_new_tokens=50)
+    nougat = Nougat(
+        model_name_or_path="custom_path",
+        min_length=10,
+        max_new_tokens=50,
+    )
     assert nougat.model_name_or_path == "custom_path"
     assert nougat.min_length == 10
     assert nougat.max_new_tokens == 50
@@ -36,11 +40,16 @@ def test_model_initialization(setup_nougat):
 
 
 @pytest.mark.parametrize(
-    "cuda_available, expected_device", [(True, "cuda"), (False, "cpu")]
+    "cuda_available, expected_device",
+    [(True, "cuda"), (False, "cpu")],
 )
-def test_device_initialization(cuda_available, expected_device, monkeypatch):
+def test_device_initialization(
+    cuda_available, expected_device, monkeypatch
+):
     monkeypatch.setattr(
-        torch, "cuda", Mock(is_available=Mock(return_value=cuda_available))
+        torch,
+        "cuda",
+        Mock(is_available=Mock(return_value=cuda_available)),
     )
     nougat = Nougat()
     assert nougat.device == expected_device
@@ -65,7 +74,9 @@ def test_get_image_invalid_path(setup_nougat):
         (10, 50),
     ],
 )
-def test_model_call_with_diff_params(setup_nougat, min_len, max_tokens):
+def test_model_call_with_diff_params(
+    setup_nougat, min_len, max_tokens
+):
     setup_nougat.min_length = min_len
     setup_nougat.max_new_tokens = max_tokens
 
@@ -96,9 +107,11 @@ def test_model_call_mocked_output(setup_nougat):
 def mock_processor_and_model():
     """Mock the NougatProcessor and VisionEncoderDecoderModel to simulate their behavior."""
     with patch(
-        "transformers.NougatProcessor.from_pretrained", return_value=Mock()
+        "transformers.NougatProcessor.from_pretrained",
+        return_value=Mock(),
     ), patch(
-        "transformers.VisionEncoderDecoderModel.from_pretrained", return_value=Mock()
+        "transformers.VisionEncoderDecoderModel.from_pretrained",
+        return_value=Mock(),
     ):
         yield
 
@@ -158,7 +171,9 @@ def test_nougat_different_model_path(setup_nougat):
 
 @pytest.mark.usefixtures("mock_processor_and_model")
 def test_nougat_bad_image_path(setup_nougat):
-    with pytest.raises(Exception):  # Adjust the exception type accordingly.
+    with pytest.raises(
+        Exception
+    ):  # Adjust the exception type accordingly.
         setup_nougat("bad_image_path.png")
 
 
diff --git a/tests/models/speech_t5.py b/tests/models/test_speech_t5.py
similarity index 77%
rename from tests/models/speech_t5.py
rename to tests/models/test_speech_t5.py
index 4e5f4cb1..a33272fc 100644
--- a/tests/models/speech_t5.py
+++ b/tests/models/test_speech_t5.py
@@ -14,10 +14,16 @@ def speecht5_model():
 
 
 def test_speecht5_init(speecht5_model):
-    assert isinstance(speecht5_model.processor, SpeechT5.processor.__class__)
+    assert isinstance(
+        speecht5_model.processor, SpeechT5.processor.__class__
+    )
     assert isinstance(speecht5_model.model, SpeechT5.model.__class__)
-    assert isinstance(speecht5_model.vocoder, SpeechT5.vocoder.__class__)
-    assert isinstance(speecht5_model.embeddings_dataset, torch.utils.data.Dataset)
+    assert isinstance(
+        speecht5_model.vocoder, SpeechT5.vocoder.__class__
+    )
+    assert isinstance(
+        speecht5_model.embeddings_dataset, torch.utils.data.Dataset
+    )
 
 
 def test_speecht5_call(speecht5_model):
@@ -41,7 +47,10 @@ def test_speecht5_set_model(speecht5_model):
     speecht5_model.set_model(new_model_name)
     assert speecht5_model.model_name == new_model_name
     assert speecht5_model.processor.model_name == new_model_name
-    assert speecht5_model.model.config.model_name_or_path == new_model_name
+    assert (
+        speecht5_model.model.config.model_name_or_path
+        == new_model_name
+    )
     speecht5_model.set_model(old_model_name)  # Restore original model
 
 
@@ -50,8 +59,13 @@ def test_speecht5_set_vocoder(speecht5_model):
     new_vocoder_name = "facebook/speecht5-hifigan"
     speecht5_model.set_vocoder(new_vocoder_name)
     assert speecht5_model.vocoder_name == new_vocoder_name
-    assert speecht5_model.vocoder.config.model_name_or_path == new_vocoder_name
-    speecht5_model.set_vocoder(old_vocoder_name)  # Restore original vocoder
+    assert (
+        speecht5_model.vocoder.config.model_name_or_path
+        == new_vocoder_name
+    )
+    speecht5_model.set_vocoder(
+        old_vocoder_name
+    )  # Restore original vocoder
 
 
 def test_speecht5_set_embeddings_dataset(speecht5_model):
@@ -59,8 +73,12 @@ def test_speecht5_set_embeddings_dataset(speecht5_model):
     new_dataset_name = "Matthijs/cmu-arctic-xvectors-test"
     speecht5_model.set_embeddings_dataset(new_dataset_name)
     assert speecht5_model.dataset_name == new_dataset_name
-    assert isinstance(speecht5_model.embeddings_dataset, torch.utils.data.Dataset)
-    speecht5_model.set_embeddings_dataset(old_dataset_name)  # Restore original dataset
+    assert isinstance(
+        speecht5_model.embeddings_dataset, torch.utils.data.Dataset
+    )
+    speecht5_model.set_embeddings_dataset(
+        old_dataset_name
+    )  # Restore original dataset
 
 
 def test_speecht5_get_sampling_rate(speecht5_model):
@@ -92,7 +110,9 @@ def test_speecht5_change_dataset_split(speecht5_model):
 def test_speecht5_load_custom_embedding(speecht5_model):
     xvector = [0.1, 0.2, 0.3, 0.4, 0.5]
     embedding = speecht5_model.load_custom_embedding(xvector)
-    assert torch.all(torch.eq(embedding, torch.tensor(xvector).unsqueeze(0)))
+    assert torch.all(
+        torch.eq(embedding, torch.tensor(xvector).unsqueeze(0))
+    )
 
 
 def test_speecht5_with_different_speakers(speecht5_model):
@@ -103,7 +123,9 @@ def test_speecht5_with_different_speakers(speecht5_model):
         assert isinstance(speech, torch.Tensor)
 
 
-def test_speecht5_save_speech_with_different_extensions(speecht5_model):
+def test_speecht5_save_speech_with_different_extensions(
+    speecht5_model,
+):
     text = "Hello, how are you?"
     speech = speecht5_model(text)
     extensions = [".wav", ".flac"]
@@ -116,7 +138,9 @@ def test_speecht5_save_speech_with_different_extensions(speecht5_model):
 
 def test_speecht5_invalid_speaker_id(speecht5_model):
     text = "Hello, how are you?"
-    invalid_speaker_id = 9999  # Speaker ID that does not exist in the dataset
+    invalid_speaker_id = (
+        9999  # Speaker ID that does not exist in the dataset
+    )
     with pytest.raises(IndexError):
         speecht5_model(text, speaker_id=invalid_speaker_id)
 
@@ -136,4 +160,6 @@ def test_speecht5_change_vocoder_model(speecht5_model):
     speecht5_model.set_vocoder(new_vocoder_name)
     speech = speecht5_model(text)
     assert isinstance(speech, torch.Tensor)
-    speecht5_model.set_vocoder(old_vocoder_name)  # Restore original vocoder
+    speecht5_model.set_vocoder(
+        old_vocoder_name
+    )  # Restore original vocoder
diff --git a/tests/models/ssd_1b.py b/tests/models/test_ssd_1b.py
similarity index 91%
rename from tests/models/ssd_1b.py
rename to tests/models/test_ssd_1b.py
index 7bd3154c..35cc4864 100644
--- a/tests/models/ssd_1b.py
+++ b/tests/models/test_ssd_1b.py
@@ -19,27 +19,37 @@ def test_ssd1b_call(ssd1b_model):
     neg_prompt = "ugly, blurry, poor quality"
     image_url = ssd1b_model(task, neg_prompt)
     assert isinstance(image_url, str)
-    assert image_url.startswith("https://")  # Assuming it starts with "https://"
+    assert image_url.startswith(
+        "https://"
+    )  # Assuming it starts with "https://"
 
 
 # Add more tests for various aspects of the class and methods
 
 
 # Example of a parameterized test for different tasks
-@pytest.mark.parametrize("task", ["A painting of a cat", "A painting of a tree"])
+@pytest.mark.parametrize(
+    "task", ["A painting of a cat", "A painting of a tree"]
+)
 def test_ssd1b_parameterized_task(ssd1b_model, task):
     image_url = ssd1b_model(task)
     assert isinstance(image_url, str)
-    assert image_url.startswith("https://")  # Assuming it starts with "https://"
+    assert image_url.startswith(
+        "https://"
+    )  # Assuming it starts with "https://"
 
 
 # Example of a test using mocks to isolate units of code
 def test_ssd1b_with_mock(ssd1b_model, mocker):
-    mocker.patch("your_module.StableDiffusionXLPipeline")  # Mock the pipeline
+    mocker.patch(
+        "your_module.StableDiffusionXLPipeline"
+    )  # Mock the pipeline
     task = "A painting of a cat"
     image_url = ssd1b_model(task)
     assert isinstance(image_url, str)
-    assert image_url.startswith("https://")  # Assuming it starts with "https://"
+    assert image_url.startswith(
+        "https://"
+    )  # Assuming it starts with "https://"
 
 
 def test_ssd1b_call_with_cache(ssd1b_model):
@@ -217,7 +227,9 @@ def test_ssd1b_repr_str(ssd1b_model):
 def test_ssd1b_rate_limited_call(ssd1b_model, mocker):
     task = "A painting of a dog"
     mocker.patch.object(
-        ssd1b_model, "__call__", side_effect=Exception("Rate limit exceeded")
+        ssd1b_model,
+        "__call__",
+        side_effect=Exception("Rate limit exceeded"),
     )
     with pytest.raises(Exception, match="Rate limit exceeded"):
         ssd1b_model.rate_limited_call(task)
diff --git a/tests/models/timm_model.py b/tests/models/test_timm_model.py
similarity index 80%
rename from tests/models/timm_model.py
rename to tests/models/test_timm_model.py
index a3e62605..97499c6a 100644
--- a/tests/models/timm_model.py
+++ b/tests/models/test_timm_model.py
@@ -6,7 +6,9 @@ from swarms.models.timm import TimmModel, TimmModelInfo
 
 @pytest.fixture
 def sample_model_info():
-    return TimmModelInfo(model_name="resnet18", pretrained=True, in_chans=3)
+    return TimmModelInfo(
+        model_name="resnet18", pretrained=True, in_chans=3
+    )
 
 
 def test_get_supported_models():
@@ -25,7 +27,9 @@ def test_create_model(sample_model_info):
 def test_call(sample_model_info):
     model_handler = TimmModel()
     input_tensor = torch.randn(1, 3, 224, 224)
-    output_shape = model_handler.__call__(sample_model_info, input_tensor)
+    output_shape = model_handler.__call__(
+        sample_model_info, input_tensor
+    )
     assert isinstance(output_shape, torch.Size)
 
 
@@ -39,7 +43,9 @@ def test_call(sample_model_info):
 )
 def test_create_model_parameterized(model_name, pretrained, in_chans):
     model_info = TimmModelInfo(
-        model_name=model_name, pretrained=pretrained, in_chans=in_chans
+        model_name=model_name,
+        pretrained=pretrained,
+        in_chans=in_chans,
     )
     model_handler = TimmModel()
     model = model_handler._create_model(model_info)
@@ -56,7 +62,9 @@ def test_create_model_parameterized(model_name, pretrained, in_chans):
 )
 def test_call_parameterized(model_name, pretrained, in_chans):
     model_info = TimmModelInfo(
-        model_name=model_name, pretrained=pretrained, in_chans=in_chans
+        model_name=model_name,
+        pretrained=pretrained,
+        in_chans=in_chans,
     )
     model_handler = TimmModel()
     input_tensor = torch.randn(1, in_chans, 224, 224)
@@ -66,7 +74,9 @@ def test_call_parameterized(model_name, pretrained, in_chans):
 
 def test_get_supported_models_mock():
     model_handler = TimmModel()
-    model_handler._get_supported_models = Mock(return_value=["resnet18", "resnet50"])
+    model_handler._get_supported_models = Mock(
+        return_value=["resnet18", "resnet50"]
+    )
     supported_models = model_handler._get_supported_models()
     assert supported_models == ["resnet18", "resnet50"]
 
@@ -80,7 +90,9 @@ def test_create_model_mock(sample_model_info):
 
 def test_call_exception():
     model_handler = TimmModel()
-    model_info = TimmModelInfo(model_name="invalid_model", pretrained=True, in_chans=3)
+    model_info = TimmModelInfo(
+        model_name="invalid_model", pretrained=True, in_chans=3
+    )
     input_tensor = torch.randn(1, 3, 224, 224)
     with pytest.raises(Exception):
         model_handler.__call__(model_info, input_tensor)
@@ -111,7 +123,9 @@ def test_environment_variable():
 @pytest.mark.slow
 def test_marked_slow():
     model_handler = TimmModel()
-    model_info = TimmModelInfo(model_name="resnet18", pretrained=True, in_chans=3)
+    model_info = TimmModelInfo(
+        model_name="resnet18", pretrained=True, in_chans=3
+    )
     input_tensor = torch.randn(1, 3, 224, 224)
     output_shape = model_handler(model_info, input_tensor)
     assert isinstance(output_shape, torch.Size)
@@ -127,7 +141,9 @@ def test_marked_slow():
 )
 def test_marked_parameterized(model_name, pretrained, in_chans):
     model_info = TimmModelInfo(
-        model_name=model_name, pretrained=pretrained, in_chans=in_chans
+        model_name=model_name,
+        pretrained=pretrained,
+        in_chans=in_chans,
     )
     model_handler = TimmModel()
     model = model_handler._create_model(model_info)
@@ -136,7 +152,9 @@ def test_marked_parameterized(model_name, pretrained, in_chans):
 
 def test_exception_testing():
     model_handler = TimmModel()
-    model_info = TimmModelInfo(model_name="invalid_model", pretrained=True, in_chans=3)
+    model_info = TimmModelInfo(
+        model_name="invalid_model", pretrained=True, in_chans=3
+    )
     input_tensor = torch.randn(1, 3, 224, 224)
     with pytest.raises(Exception):
         model_handler.__call__(model_info, input_tensor)
@@ -144,7 +162,9 @@ def test_exception_testing():
 
 def test_parameterized_testing():
     model_handler = TimmModel()
-    model_info = TimmModelInfo(model_name="resnet18", pretrained=True, in_chans=3)
+    model_info = TimmModelInfo(
+        model_name="resnet18", pretrained=True, in_chans=3
+    )
     input_tensor = torch.randn(1, 3, 224, 224)
     output_shape = model_handler.__call__(model_info, input_tensor)
     assert isinstance(output_shape, torch.Size)
@@ -153,7 +173,9 @@ def test_parameterized_testing():
 def test_use_mocks_and_monkeypatching():
     model_handler = TimmModel()
     model_handler._create_model = Mock(return_value=torch.nn.Module())
-    model_info = TimmModelInfo(model_name="resnet18", pretrained=True, in_chans=3)
+    model_info = TimmModelInfo(
+        model_name="resnet18", pretrained=True, in_chans=3
+    )
     model = model_handler._create_model(model_info)
     assert isinstance(model, torch.nn.Module)
 
diff --git a/tests/models/vilt.py b/tests/models/test_vilt.py
similarity index 86%
rename from tests/models/vilt.py
rename to tests/models/test_vilt.py
index b376f41b..99e6848e 100644
--- a/tests/models/vilt.py
+++ b/tests/models/test_vilt.py
@@ -19,13 +19,17 @@ def test_vilt_initialization(vilt_instance):
 # 2. Test Model Predictions
 @patch.object(requests, "get")
 @patch.object(Image, "open")
-def test_vilt_prediction(mock_image_open, mock_requests_get, vilt_instance):
+def test_vilt_prediction(
+    mock_image_open, mock_requests_get, vilt_instance
+):
     mock_image = Mock()
     mock_image_open.return_value = mock_image
     mock_requests_get.return_value.raw = Mock()
 
     # It's a mock response, so no real answer expected
-    with pytest.raises(Exception):  # Ensure exception is more specific
+    with pytest.raises(
+        Exception
+    ):  # Ensure exception is more specific
         vilt_instance(
             "What is this image",
             "https://images.unsplash.com/photo-1582538885592-e70a5d7ab3d3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1770&q=80",
@@ -33,7 +37,11 @@ def test_vilt_prediction(mock_image_open, mock_requests_get, vilt_instance):
 
 
 # 3. Test Exception Handling for network
-@patch.object(requests, "get", side_effect=requests.RequestException("Network error"))
+@patch.object(
+    requests,
+    "get",
+    side_effect=requests.RequestException("Network error"),
+)
 def test_vilt_network_exception(vilt_instance):
     with pytest.raises(requests.RequestException):
         vilt_instance(
@@ -48,12 +56,17 @@ def test_vilt_network_exception(vilt_instance):
     [
         ("What is this?", "http://example.com/image1.jpg"),
         ("Who is in the image?", "http://example.com/image2.jpg"),
-        ("Where was this picture taken?", "http://example.com/image3.jpg"),
+        (
+            "Where was this picture taken?",
+            "http://example.com/image3.jpg",
+        ),
         # ... Add more scenarios
     ],
 )
 def test_vilt_various_inputs(text, image_url, vilt_instance):
-    with pytest.raises(Exception):  # Again, ensure exception is more specific
+    with pytest.raises(
+        Exception
+    ):  # Again, ensure exception is more specific
         vilt_instance(text, image_url)
 
 
diff --git a/tests/models/whisperx.py b/tests/models/test_whisperx.py
similarity index 89%
rename from tests/models/whisperx.py
rename to tests/models/test_whisperx.py
index bcbd02e9..4b0e4120 100644
--- a/tests/models/whisperx.py
+++ b/tests/models/test_whisperx.py
@@ -7,7 +7,7 @@ import pytest
 import whisperx
 from pydub import AudioSegment
 from pytube import YouTube
-from swarms.models.whisperx import WhisperX
+from swarms.models.whisperx_model import WhisperX
 
 
 # Fixture to create a temporary directory for testing
@@ -28,11 +28,15 @@ def test_speech_to_text_install(mock_run):
 # Mock pytube.YouTube and pytube.Streams for download tests
 @patch("pytube.YouTube")
 @patch.object(YouTube, "streams")
-def test_speech_to_text_download_youtube_video(mock_streams, mock_youtube, temp_dir):
+def test_speech_to_text_download_youtube_video(
+    mock_streams, mock_youtube, temp_dir
+):
     # Mock YouTube and streams
     video_url = "https://www.youtube.com/watch?v=MJd6pr16LRM"
     mock_stream = mock_streams().filter().first()
-    mock_stream.download.return_value = os.path.join(temp_dir, "video.mp4")
+    mock_stream.download.return_value = os.path.join(
+        temp_dir, "video.mp4"
+    )
     mock_youtube.return_value = mock_youtube
     mock_youtube.streams = mock_streams
 
@@ -66,7 +70,9 @@ def test_speech_to_text_transcribe_youtube_video(
 
     mock_load_audio.return_value = "audio_path"
     mock_align_model.return_value = (mock_align_model, "metadata")
-    mock_align.return_value = {"segments": [{"text": "Hello, World!"}]}
+    mock_align.return_value = {
+        "segments": [{"text": "Hello, World!"}]
+    }
 
     # Mock diarization pipeline
     mock_diarization.return_value = None
@@ -116,7 +122,11 @@ def test_speech_to_text_transcribe_whisperx_failure(
 @patch("whisperx.align")
 @patch.object(whisperx.DiarizationPipeline, "__call__")
 def test_speech_to_text_transcribe_missing_segments(
-    mock_diarization, mock_align, mock_align_model, mock_load_audio, mock_load_model
+    mock_diarization,
+    mock_align,
+    mock_align_model,
+    mock_load_audio,
+    mock_load_model,
 ):
     # Mock whisperx functions to return incomplete output
     mock_load_model.return_value = mock_load_model
@@ -142,7 +152,11 @@ def test_speech_to_text_transcribe_missing_segments(
 @patch("whisperx.align")
 @patch.object(whisperx.DiarizationPipeline, "__call__")
 def test_speech_to_text_transcribe_align_failure(
-    mock_diarization, mock_align, mock_align_model, mock_load_audio, mock_load_model
+    mock_diarization,
+    mock_align,
+    mock_align_model,
+    mock_load_audio,
+    mock_load_model,
 ):
     # Mock whisperx functions to raise an exception during align
     mock_load_model.return_value = mock_load_model
@@ -183,14 +197,18 @@ def test_speech_to_text_transcribe_diarization_failure(
     # Mock YouTube and streams
     video_url = "https://www.youtube.com/watch?v=MJd6pr16LRM"
     mock_stream = mock_streams().filter().first()
-    mock_stream.download.return_value = os.path.join(temp_dir, "video.mp4")
+    mock_stream.download.return_value = os.path.join(
+        temp_dir, "video.mp4"
+    )
     mock_youtube.return_value = mock_youtube
     mock_youtube.streams = mock_streams
 
     # Mock whisperx functions
     mock_load_audio.return_value = "audio_path"
     mock_align_model.return_value = (mock_align_model, "metadata")
-    mock_align.return_value = {"segments": [{"text": "Hello, World!"}]}
+    mock_align.return_value = {
+        "segments": [{"text": "Hello, World!"}]
+    }
 
     # Mock diarization pipeline to raise an exception
     mock_diarization.side_effect = Exception("Diarization failed")
diff --git a/tests/models/yi_200k.py b/tests/models/test_yi_200k.py
similarity index 77%
rename from tests/models/yi_200k.py
rename to tests/models/test_yi_200k.py
index 72a6d1b2..9f3c236f 100644
--- a/tests/models/yi_200k.py
+++ b/tests/models/test_yi_200k.py
@@ -31,7 +31,9 @@ def test_yi34b_generate_text_with_length(yi34b_model, max_length):
 
 
 @pytest.mark.parametrize("temperature", [0.5, 1.0, 1.5])
-def test_yi34b_generate_text_with_temperature(yi34b_model, temperature):
+def test_yi34b_generate_text_with_temperature(
+    yi34b_model, temperature
+):
     prompt = "There's a place where time stands still."
     generated_text = yi34b_model(prompt, temperature=temperature)
     assert isinstance(generated_text, str)
@@ -39,21 +41,27 @@ def test_yi34b_generate_text_with_temperature(yi34b_model, temperature):
 
 def test_yi34b_generate_text_with_invalid_prompt(yi34b_model):
     prompt = None  # Invalid prompt
-    with pytest.raises(ValueError, match="Input prompt must be a non-empty string"):
+    with pytest.raises(
+        ValueError, match="Input prompt must be a non-empty string"
+    ):
         yi34b_model(prompt)
 
 
 def test_yi34b_generate_text_with_invalid_max_length(yi34b_model):
     prompt = "There's a place where time stands still."
     max_length = -1  # Invalid max_length
-    with pytest.raises(ValueError, match="max_length must be a positive integer"):
+    with pytest.raises(
+        ValueError, match="max_length must be a positive integer"
+    ):
         yi34b_model(prompt, max_length=max_length)
 
 
 def test_yi34b_generate_text_with_invalid_temperature(yi34b_model):
     prompt = "There's a place where time stands still."
     temperature = 2.0  # Invalid temperature
-    with pytest.raises(ValueError, match="temperature must be between 0.01 and 1.0"):
+    with pytest.raises(
+        ValueError, match="temperature must be between 0.01 and 1.0"
+    ):
         yi34b_model(prompt, temperature=temperature)
 
 
@@ -74,28 +82,41 @@ def test_yi34b_generate_text_with_top_p(yi34b_model, top_p):
 def test_yi34b_generate_text_with_invalid_top_k(yi34b_model):
     prompt = "There's a place where time stands still."
     top_k = -1  # Invalid top_k
-    with pytest.raises(ValueError, match="top_k must be a non-negative integer"):
+    with pytest.raises(
+        ValueError, match="top_k must be a non-negative integer"
+    ):
         yi34b_model(prompt, top_k=top_k)
 
 
 def test_yi34b_generate_text_with_invalid_top_p(yi34b_model):
     prompt = "There's a place where time stands still."
     top_p = 1.5  # Invalid top_p
-    with pytest.raises(ValueError, match="top_p must be between 0.0 and 1.0"):
+    with pytest.raises(
+        ValueError, match="top_p must be between 0.0 and 1.0"
+    ):
         yi34b_model(prompt, top_p=top_p)
 
 
 @pytest.mark.parametrize("repitition_penalty", [1.0, 1.2, 1.5])
-def test_yi34b_generate_text_with_repitition_penalty(yi34b_model, repitition_penalty):
+def test_yi34b_generate_text_with_repitition_penalty(
+    yi34b_model, repitition_penalty
+):
     prompt = "There's a place where time stands still."
-    generated_text = yi34b_model(prompt, repitition_penalty=repitition_penalty)
+    generated_text = yi34b_model(
+        prompt, repitition_penalty=repitition_penalty
+    )
     assert isinstance(generated_text, str)
 
 
-def test_yi34b_generate_text_with_invalid_repitition_penalty(yi34b_model):
+def test_yi34b_generate_text_with_invalid_repitition_penalty(
+    yi34b_model,
+):
     prompt = "There's a place where time stands still."
     repitition_penalty = 0.0  # Invalid repitition_penalty
-    with pytest.raises(ValueError, match="repitition_penalty must be a positive float"):
+    with pytest.raises(
+        ValueError,
+        match="repitition_penalty must be a positive float",
+    ):
         yi34b_model(prompt, repitition_penalty=repitition_penalty)
 
 
diff --git a/tests/structs/nonlinear_workflow.py b/tests/structs/nonlinear_workflow.py
deleted file mode 100644
index ad7e57d0..00000000
--- a/tests/structs/nonlinear_workflow.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from unittest.mock import patch, MagicMock
-from swarms.structs.nonlinear_workflow import NonLinearWorkflow, Task
-
-
-class MockTask(Task):
-    def can_execute(self):
-        return True
-
-    def execute(self):
-        return "Task executed"
-
-
-def test_nonlinearworkflow_initialization():
-    agents = MagicMock()
-    iters_per_task = MagicMock()
-    workflow = NonLinearWorkflow(agents, iters_per_task)
-    assert isinstance(workflow, NonLinearWorkflow)
-    assert workflow.agents == agents
-    assert workflow.tasks == []
-
-
-def test_nonlinearworkflow_add():
-    agents = MagicMock()
-    iters_per_task = MagicMock()
-    workflow = NonLinearWorkflow(agents, iters_per_task)
-    task = MockTask("task1")
-    workflow.add(task)
-    assert workflow.tasks == [task]
-
-
-@patch("your_module.NonLinearWorkflow.is_finished")
-@patch("your_module.NonLinearWorkflow.output_tasks")
-def test_nonlinearworkflow_run(mock_output_tasks, mock_is_finished):
-    agents = MagicMock()
-    iters_per_task = MagicMock()
-    workflow = NonLinearWorkflow(agents, iters_per_task)
-    task = MockTask("task1")
-    workflow.add(task)
-    mock_is_finished.return_value = False
-    mock_output_tasks.return_value = [task]
-    workflow.run()
-    assert mock_output_tasks.called
-
-
-def test_nonlinearworkflow_output_tasks():
-    agents = MagicMock()
-    iters_per_task = MagicMock()
-    workflow = NonLinearWorkflow(agents, iters_per_task)
-    task = MockTask("task1")
-    workflow.add(task)
-    assert workflow.output_tasks() == [task]
-
-
-def test_nonlinearworkflow_to_graph():
-    agents = MagicMock()
-    iters_per_task = MagicMock()
-    workflow = NonLinearWorkflow(agents, iters_per_task)
-    task = MockTask("task1")
-    workflow.add(task)
-    assert workflow.to_graph() == {"task1": set()}
-
-
-def test_nonlinearworkflow_order_tasks():
-    agents = MagicMock()
-    iters_per_task = MagicMock()
-    workflow = NonLinearWorkflow(agents, iters_per_task)
-    task = MockTask("task1")
-    workflow.add(task)
-    assert workflow.order_tasks() == [task]
diff --git a/tests/structs/flow.py b/tests/structs/test_agent.py
similarity index 80%
rename from tests/structs/flow.py
rename to tests/structs/test_agent.py
index edc4b9c7..a8e1cf92 100644
--- a/tests/structs/flow.py
+++ b/tests/structs/test_agent.py
@@ -7,7 +7,7 @@ import pytest
 from dotenv import load_dotenv
 
 from swarms.models import OpenAIChat
-from swarms.structs.flow import Flow, stop_when_repeats
+from swarms.structs.agent import Agent, stop_when_repeats
 from swarms.utils.logger import logger
 
 load_dotenv()
@@ -25,12 +25,16 @@ def mocked_llm():
 
 @pytest.fixture
 def basic_flow(mocked_llm):
-    return Flow(llm=mocked_llm, max_loops=5)
+    return Agent(llm=mocked_llm, max_loops=5)
 
 
 @pytest.fixture
 def flow_with_condition(mocked_llm):
-    return Flow(llm=mocked_llm, max_loops=5, stopping_condition=stop_when_repeats)
+    return Agent(
+        llm=mocked_llm,
+        max_loops=5,
+        stopping_condition=stop_when_repeats,
+    )
 
 
 # Basic Tests
@@ -61,11 +65,15 @@ def test_provide_feedback(basic_flow):
 @patch("time.sleep", return_value=None)  # to speed up tests
 def test_run_without_stopping_condition(mocked_sleep, basic_flow):
     response = basic_flow.run("Test task")
-    assert response == "Test task"  # since our mocked llm doesn't modify the response
+    assert (
+        response == "Test task"
+    )  # since our mocked llm doesn't modify the response
 
 
 @patch("time.sleep", return_value=None)  # to speed up tests
-def test_run_with_stopping_condition(mocked_sleep, flow_with_condition):
+def test_run_with_stopping_condition(
+    mocked_sleep, flow_with_condition
+):
     response = flow_with_condition.run("Stop")
     assert response == "Stop"
 
@@ -89,7 +97,7 @@ def test_save_and_load(basic_flow, tmp_path):
     basic_flow.memory.append(["Test1", "Test2"])
     basic_flow.save(file_path)
 
-    new_flow = Flow(llm=mocked_llm, max_loops=5)
+    new_flow = Agent(llm=mocked_llm, max_loops=5)
     new_flow.load(file_path)
     assert new_flow.memory == [["Test1", "Test2"]]
 
@@ -103,17 +111,21 @@ def test_env_variable_handling(monkeypatch):
 # TODO: Add more tests, especially edge cases and exception cases. Implement parametrized tests for varied inputs.
 
 
-# Test initializing the flow with different stopping conditions
+# Test initializing the agent with different stopping conditions
 def test_flow_with_custom_stopping_condition(mocked_llm):
     def stopping_condition(x):
         return "terminate" in x.lower()
 
-    flow = Flow(llm=mocked_llm, max_loops=5, stopping_condition=stopping_condition)
-    assert flow.stopping_condition("Please terminate now")
-    assert not flow.stopping_condition("Continue the process")
+    agent = Agent(
+        llm=mocked_llm,
+        max_loops=5,
+        stopping_condition=stopping_condition,
+    )
+    assert agent.stopping_condition("Please terminate now")
+    assert not agent.stopping_condition("Continue the process")
 
 
-# Test calling the flow directly
+# Test calling the agent directly
 def test_flow_call(basic_flow):
     response = basic_flow("Test call")
     assert response == "Test call"
@@ -121,7 +133,9 @@ def test_flow_call(basic_flow):
 
 # Test formatting the prompt
 def test_format_prompt(basic_flow):
-    formatted_prompt = basic_flow.format_prompt("Hello {name}", name="John")
+    formatted_prompt = basic_flow.format_prompt(
+        "Hello {name}", name="John"
+    )
     assert formatted_prompt == "Hello John"
 
 
@@ -149,7 +163,11 @@ def test_interactive_mode(basic_flow):
 
 # Test bulk run with varied inputs
 def test_bulk_run_varied_inputs(basic_flow):
-    inputs = [{"task": "Test1"}, {"task": "Test2"}, {"task": "Stop now"}]
+    inputs = [
+        {"task": "Test1"},
+        {"task": "Test2"},
+        {"task": "Stop now"},
+    ]
     responses = basic_flow.bulk_run(inputs)
     assert responses == ["Test1", "Test2", "Stop now"]
 
@@ -173,20 +191,24 @@ def test_save_different_memory(basic_flow, tmp_path):
 
 # Test the stopping condition check
 def test_check_stopping_condition(flow_with_condition):
-    assert flow_with_condition._check_stopping_condition("Stop this process")
-    assert not flow_with_condition._check_stopping_condition("Continue the task")
+    assert flow_with_condition._check_stopping_condition(
+        "Stop this process"
+    )
+    assert not flow_with_condition._check_stopping_condition(
+        "Continue the task"
+    )
 
 
 # Test without providing max loops (default value should be 5)
 def test_default_max_loops(mocked_llm):
-    flow = Flow(llm=mocked_llm)
-    assert flow.max_loops == 5
+    agent = Agent(llm=mocked_llm)
+    assert agent.max_loops == 5
 
 
-# Test creating flow from llm and template
+# Test creating agent from llm and template
 def test_from_llm_and_template(mocked_llm):
-    flow = Flow.from_llm_and_template(mocked_llm, "Test template")
-    assert isinstance(flow, Flow)
+    agent = Agent.from_llm_and_template(mocked_llm, "Test template")
+    assert isinstance(agent, Agent)
 
 
 # Mocking the OpenAIChat for testing
@@ -194,8 +216,8 @@ def test_from_llm_and_template(mocked_llm):
 def test_mocked_openai_chat(MockedOpenAIChat):
     llm = MockedOpenAIChat(openai_api_key=openai_api_key)
     llm.return_value = MagicMock()
-    flow = Flow(llm=llm, max_loops=5)
-    flow.run("Mocked run")
+    agent = Agent(llm=llm, max_loops=5)
+    agent.run("Mocked run")
     assert MockedOpenAIChat.called
 
 
@@ -203,7 +225,10 @@ def test_mocked_openai_chat(MockedOpenAIChat):
 @patch("time.sleep", return_value=None)
 def test_retry_attempts(mocked_sleep, basic_flow):
     basic_flow.retry_attempts = 2
-    basic_flow.llm.side_effect = [Exception("Test Exception"), "Valid response"]
+    basic_flow.llm.side_effect = [
+        Exception("Test Exception"),
+        "Valid response",
+    ]
     response = basic_flow.run("Test retry")
     assert response == "Valid response"
 
@@ -224,16 +249,18 @@ def test_different_retry_intervals(mocked_sleep, basic_flow):
     assert response == "Test retry interval"
 
 
-# Test invoking the flow with additional kwargs
+# Test invoking the agent with additional kwargs
 @patch("time.sleep", return_value=None)
 def test_flow_call_with_kwargs(mocked_sleep, basic_flow):
-    response = basic_flow("Test call", param1="value1", param2="value2")
+    response = basic_flow(
+        "Test call", param1="value1", param2="value2"
+    )
     assert response == "Test call"
 
 
-# Test initializing the flow with all parameters
+# Test initializing the agent with all parameters
 def test_flow_initialization_all_params(mocked_llm):
-    flow = Flow(
+    agent = Agent(
         llm=mocked_llm,
         max_loops=10,
         stopping_condition=stop_when_repeats,
@@ -244,11 +271,11 @@ def test_flow_initialization_all_params(mocked_llm):
         param1="value1",
         param2="value2",
     )
-    assert flow.max_loops == 10
-    assert flow.loop_interval == 2
-    assert flow.retry_attempts == 4
-    assert flow.retry_interval == 2
-    assert flow.interactive
+    assert agent.max_loops == 10
+    assert agent.loop_interval == 2
+    assert agent.retry_attempts == 4
+    assert agent.retry_interval == 2
+    assert agent.interactive
 
 
 # Test the stopping token is in the response
@@ -260,30 +287,30 @@ def test_stopping_token_in_response(mocked_sleep, basic_flow):
 
 @pytest.fixture
 def flow_instance():
-    # Create an instance of the Flow class with required parameters for testing
+    # Create an instance of the Agent class with required parameters for testing
     # You may need to adjust this based on your actual class initialization
     llm = OpenAIChat(
         openai_api_key=openai_api_key,
     )
-    flow = Flow(
+    agent = Agent(
         llm=llm,
         max_loops=5,
         interactive=False,
         dashboard=False,
         dynamic_temperature=False,
     )
-    return flow
+    return agent
 
 
 def test_flow_run(flow_instance):
-    # Test the basic run method of the Flow class
+    # Test the basic run method of the Agent class
     response = flow_instance.run("Test task")
     assert isinstance(response, str)
     assert len(response) > 0
 
 
 def test_flow_interactive_mode(flow_instance):
-    # Test the interactive mode of the Flow class
+    # Test the interactive mode of the Agent class
     flow_instance.interactive = True
     response = flow_instance.run("Test task")
     assert isinstance(response, str)
@@ -291,7 +318,7 @@ def test_flow_interactive_mode(flow_instance):
 
 
 def test_flow_dashboard_mode(flow_instance):
-    # Test the dashboard mode of the Flow class
+    # Test the dashboard mode of the Agent class
     flow_instance.dashboard = True
     response = flow_instance.run("Test task")
     assert isinstance(response, str)
@@ -299,7 +326,7 @@ def test_flow_dashboard_mode(flow_instance):
 
 
 def test_flow_autosave(flow_instance):
-    # Test the autosave functionality of the Flow class
+    # Test the autosave functionality of the Agent class
     flow_instance.autosave = True
     response = flow_instance.run("Test task")
     assert isinstance(response, str)
@@ -311,7 +338,9 @@ def test_flow_autosave(flow_instance):
 def test_flow_response_filtering(flow_instance):
     # Test the response filtering functionality
     flow_instance.add_response_filter("filter_this")
-    response = flow_instance.filtered_run("This message should filter_this")
+    response = flow_instance.filtered_run(
+        "This message should filter_this"
+    )
     assert "filter_this" not in response
 
 
@@ -352,7 +381,7 @@ def test_flow_graceful_shutdown(flow_instance):
     assert result is not None
 
 
-# Add more test cases as needed to cover various aspects of your Flow class
+# Add more test cases as needed to cover various aspects of your Agent class
 
 
 def test_flow_max_loops(flow_instance):
@@ -370,9 +399,12 @@ def test_flow_autosave_path(flow_instance):
 def test_flow_response_length(flow_instance):
     # Test checking the length of the response
     response = flow_instance.run(
-        "Generate a 10,000 word long blog on mental clarity and the benefits of meditation."
+        "Generate a 10,000 word long blog on mental clarity and the"
+        " benefits of meditation."
+    )
+    assert (
+        len(response) > flow_instance.get_response_length_threshold()
     )
-    assert len(response) > flow_instance.get_response_length_threshold()
 
 
 def test_flow_set_response_length_threshold(flow_instance):
@@ -461,7 +493,9 @@ def test_flow_get_conversation_log(flow_instance):
     flow_instance.run("Message 1")
     flow_instance.run("Message 2")
     conversation_log = flow_instance.get_conversation_log()
-    assert len(conversation_log) == 4  # Including system and user messages
+    assert (
+        len(conversation_log) == 4
+    )  # Including system and user messages
 
 
 def test_flow_clear_conversation_log(flow_instance):
@@ -473,7 +507,7 @@ def test_flow_clear_conversation_log(flow_instance):
 
 
 def test_flow_get_state(flow_instance):
-    # Test getting the current state of the Flow instance
+    # Test getting the current state of the Agent instance
     state = flow_instance.get_state()
     assert isinstance(state, dict)
     assert "current_prompt" in state
@@ -489,7 +523,7 @@ def test_flow_get_state(flow_instance):
 
 
 def test_flow_load_state(flow_instance):
-    # Test loading the state into the Flow instance
+    # Test loading the state into the Agent instance
     state = {
         "current_prompt": "Loaded prompt",
         "instructions": ["Step 1", "Step 2"],
@@ -521,7 +555,7 @@ def test_flow_load_state(flow_instance):
 
 
 def test_flow_save_state(flow_instance):
-    # Test saving the state of the Flow instance
+    # Test saving the state of the Agent instance
     flow_instance.change_prompt("New prompt")
     flow_instance.add_instruction("Step 1")
     flow_instance.add_user_message("User message")
@@ -545,19 +579,37 @@ def test_flow_rollback(flow_instance):
     flow_instance.change_prompt("New prompt")
     state2 = flow_instance.get_state()
     flow_instance.rollback_to_state(state1)
-    assert flow_instance.get_current_prompt() == state1["current_prompt"]
+    assert (
+        flow_instance.get_current_prompt() == state1["current_prompt"]
+    )
     assert flow_instance.get_instructions() == state1["instructions"]
-    assert flow_instance.get_user_messages() == state1["user_messages"]
-    assert flow_instance.get_response_history() == state1["response_history"]
-    assert flow_instance.get_conversation_log() == state1["conversation_log"]
-    assert flow_instance.is_dynamic_pacing_enabled() == state1["dynamic_pacing_enabled"]
+    assert (
+        flow_instance.get_user_messages() == state1["user_messages"]
+    )
+    assert (
+        flow_instance.get_response_history()
+        == state1["response_history"]
+    )
+    assert (
+        flow_instance.get_conversation_log()
+        == state1["conversation_log"]
+    )
+    assert (
+        flow_instance.is_dynamic_pacing_enabled()
+        == state1["dynamic_pacing_enabled"]
+    )
     assert (
         flow_instance.get_response_length_threshold()
         == state1["response_length_threshold"]
     )
-    assert flow_instance.get_response_filters() == state1["response_filters"]
+    assert (
+        flow_instance.get_response_filters()
+        == state1["response_filters"]
+    )
     assert flow_instance.get_max_loops() == state1["max_loops"]
-    assert flow_instance.get_autosave_path() == state1["autosave_path"]
+    assert (
+        flow_instance.get_autosave_path() == state1["autosave_path"]
+    )
     assert flow_instance.get_state() == state1
 
 
@@ -565,7 +617,9 @@ def test_flow_contextual_intent(flow_instance):
     # Test contextual intent handling
     flow_instance.add_context("location", "New York")
     flow_instance.add_context("time", "tomorrow")
-    response = flow_instance.run("What's the weather like in {location} at {time}?")
+    response = flow_instance.run(
+        "What's the weather like in {location} at {time}?"
+    )
     assert "New York" in response
     assert "tomorrow" in response
 
@@ -573,9 +627,13 @@ def test_flow_contextual_intent(flow_instance):
 def test_flow_contextual_intent_override(flow_instance):
     # Test contextual intent override
     flow_instance.add_context("location", "New York")
-    response1 = flow_instance.run("What's the weather like in {location}?")
+    response1 = flow_instance.run(
+        "What's the weather like in {location}?"
+    )
     flow_instance.add_context("location", "Los Angeles")
-    response2 = flow_instance.run("What's the weather like in {location}?")
+    response2 = flow_instance.run(
+        "What's the weather like in {location}?"
+    )
     assert "New York" in response1
     assert "Los Angeles" in response2
 
@@ -583,14 +641,18 @@ def test_flow_contextual_intent_override(flow_instance):
 def test_flow_contextual_intent_reset(flow_instance):
     # Test resetting contextual intent
     flow_instance.add_context("location", "New York")
-    response1 = flow_instance.run("What's the weather like in {location}?")
+    response1 = flow_instance.run(
+        "What's the weather like in {location}?"
+    )
     flow_instance.reset_context()
-    response2 = flow_instance.run("What's the weather like in {location}?")
+    response2 = flow_instance.run(
+        "What's the weather like in {location}?"
+    )
     assert "New York" in response1
     assert "New York" in response2
 
 
-# Add more test cases as needed to cover various aspects of your Flow class
+# Add more test cases as needed to cover various aspects of your Agent class
 def test_flow_interruptible(flow_instance):
     # Test interruptible mode
     flow_instance.interruptible = True
@@ -610,7 +672,9 @@ def test_flow_non_interruptible(flow_instance):
 def test_flow_timeout(flow_instance):
     # Test conversation timeout
     flow_instance.timeout = 60  # Set a timeout of 60 seconds
-    response = flow_instance.run("This should take some time to respond.")
+    response = flow_instance.run(
+        "This should take some time to respond."
+    )
     assert "Timed out" in response
     assert flow_instance.is_timed_out() is True
 
@@ -659,14 +723,20 @@ def test_flow_save_and_load_conversation(flow_instance):
 
 def test_flow_inject_custom_system_message(flow_instance):
     # Test injecting a custom system message into the conversation
-    flow_instance.inject_custom_system_message("Custom system message")
-    assert "Custom system message" in flow_instance.get_message_history()
+    flow_instance.inject_custom_system_message(
+        "Custom system message"
+    )
+    assert (
+        "Custom system message" in flow_instance.get_message_history()
+    )
 
 
 def test_flow_inject_custom_user_message(flow_instance):
     # Test injecting a custom user message into the conversation
     flow_instance.inject_custom_user_message("Custom user message")
-    assert "Custom user message" in flow_instance.get_message_history()
+    assert (
+        "Custom user message" in flow_instance.get_message_history()
+    )
 
 
 def test_flow_inject_custom_response(flow_instance):
@@ -677,27 +747,45 @@ def test_flow_inject_custom_response(flow_instance):
 
 def test_flow_clear_injected_messages(flow_instance):
     # Test clearing injected messages from the conversation
-    flow_instance.inject_custom_system_message("Custom system message")
+    flow_instance.inject_custom_system_message(
+        "Custom system message"
+    )
     flow_instance.inject_custom_user_message("Custom user message")
     flow_instance.inject_custom_response("Custom response")
     flow_instance.clear_injected_messages()
-    assert "Custom system message" not in flow_instance.get_message_history()
-    assert "Custom user message" not in flow_instance.get_message_history()
-    assert "Custom response" not in flow_instance.get_message_history()
+    assert (
+        "Custom system message"
+        not in flow_instance.get_message_history()
+    )
+    assert (
+        "Custom user message"
+        not in flow_instance.get_message_history()
+    )
+    assert (
+        "Custom response" not in flow_instance.get_message_history()
+    )
 
 
 def test_flow_disable_message_history(flow_instance):
     # Test disabling message history recording
     flow_instance.disable_message_history()
-    response = flow_instance.run("This message should not be recorded in history.")
-    assert "This message should not be recorded in history." in response
-    assert len(flow_instance.get_message_history()) == 0  # History is empty
+    response = flow_instance.run(
+        "This message should not be recorded in history."
+    )
+    assert (
+        "This message should not be recorded in history." in response
+    )
+    assert (
+        len(flow_instance.get_message_history()) == 0
+    )  # History is empty
 
 
 def test_flow_enable_message_history(flow_instance):
     # Test enabling message history recording
     flow_instance.enable_message_history()
-    response = flow_instance.run("This message should be recorded in history.")
+    response = flow_instance.run(
+        "This message should be recorded in history."
+    )
     assert "This message should be recorded in history." in response
     assert len(flow_instance.get_message_history()) == 1
 
@@ -707,7 +795,9 @@ def test_flow_custom_logger(flow_instance):
     custom_logger = logger  # Replace with your custom logger class
     flow_instance.set_logger(custom_logger)
     response = flow_instance.run("Custom logger test")
-    assert "Logged using custom logger" in response  # Verify logging message
+    assert (
+        "Logged using custom logger" in response
+    )  # Verify logging message
 
 
 def test_flow_batch_processing(flow_instance):
@@ -775,9 +865,9 @@ def test_flow_clear_context(flow_instance):
 
 
 def test_flow_input_validation(flow_instance):
-    # Test input validation for invalid flow configurations
+    # Test input validation for invalid agent configurations
     with pytest.raises(ValueError):
-        Flow(config=None)  # Invalid config, should raise ValueError
+        Agent(config=None)  # Invalid config, should raise ValueError
 
     with pytest.raises(ValueError):
         flow_instance.set_message_delimiter(
@@ -800,16 +890,24 @@ def test_flow_input_validation(flow_instance):
         )  # Invalid logger type, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.add_context(None, "value")  # None key, should raise ValueError
+        flow_instance.add_context(
+            None, "value"
+        )  # None key, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.add_context("key", None)  # None value, should raise ValueError
+        flow_instance.add_context(
+            "key", None
+        )  # None value, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.update_context(None, "value")  # None key, should raise ValueError
+        flow_instance.update_context(
+            None, "value"
+        )  # None key, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.update_context("key", None)  # None value, should raise ValueError
+        flow_instance.update_context(
+            "key", None
+        )  # None value, should raise ValueError
 
 
 def test_flow_conversation_reset(flow_instance):
@@ -826,7 +924,7 @@ def test_flow_conversation_persistence(flow_instance):
     flow_instance.run("Message 2")
     conversation = flow_instance.get_conversation()
 
-    new_flow_instance = Flow()
+    new_flow_instance = Agent()
     new_flow_instance.load_conversation(conversation)
     assert len(new_flow_instance.get_message_history()) == 2
     assert "Message 1" in new_flow_instance.get_message_history()[0]
@@ -894,7 +992,7 @@ def test_flow_multiple_event_listeners(flow_instance):
         mock_second_response.assert_called_once()
 
 
-# Add more test cases as needed to cover various aspects of your Flow class
+# Add more test cases as needed to cover various aspects of your Agent class
 def test_flow_error_handling(flow_instance):
     # Test error handling and exceptions
     with pytest.raises(ValueError):
@@ -913,16 +1011,24 @@ def test_flow_error_handling(flow_instance):
         )  # Invalid logger type, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.add_context(None, "value")  # None key, should raise ValueError
+        flow_instance.add_context(
+            None, "value"
+        )  # None key, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.add_context("key", None)  # None value, should raise ValueError
+        flow_instance.add_context(
+            "key", None
+        )  # None value, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.update_context(None, "value")  # None key, should raise ValueError
+        flow_instance.update_context(
+            None, "value"
+        )  # None key, should raise ValueError
 
     with pytest.raises(ValueError):
-        flow_instance.update_context("key", None)  # None value, should raise ValueError
+        flow_instance.update_context(
+            "key", None
+        )  # None value, should raise ValueError
 
 
 def test_flow_context_operations(flow_instance):
@@ -935,7 +1041,7 @@ def test_flow_context_operations(flow_instance):
     assert flow_instance.get_context("user_id") is None
 
 
-# Add more test cases as needed to cover various aspects of your Flow class
+# Add more test cases as needed to cover various aspects of your Agent class
 
 
 def test_flow_long_messages(flow_instance):
@@ -959,8 +1065,14 @@ def test_flow_custom_response(flow_instance):
     flow_instance.set_response_generator(custom_response_generator)
 
     assert flow_instance.run("Hello") == "Hi there!"
-    assert flow_instance.run("How are you?") == "I'm doing well, thank you."
-    assert flow_instance.run("What's your name?") == "I don't understand."
+    assert (
+        flow_instance.run("How are you?")
+        == "I'm doing well, thank you."
+    )
+    assert (
+        flow_instance.run("What's your name?")
+        == "I don't understand."
+    )
 
 
 def test_flow_message_validation(flow_instance):
@@ -971,8 +1083,12 @@ def test_flow_message_validation(flow_instance):
     flow_instance.set_message_validator(custom_message_validator)
 
     assert flow_instance.run("Valid message") is not None
-    assert flow_instance.run("") is None  # Empty message should be rejected
-    assert flow_instance.run(None) is None  # None message should be rejected
+    assert (
+        flow_instance.run("") is None
+    )  # Empty message should be rejected
+    assert (
+        flow_instance.run(None) is None
+    )  # None message should be rejected
 
 
 def test_flow_custom_logging(flow_instance):
@@ -985,7 +1101,7 @@ def test_flow_custom_logging(flow_instance):
 
 
 def test_flow_performance(flow_instance):
-    # Test the performance of the Flow class by running a large number of messages
+    # Test the performance of the Agent class by running a large number of messages
     num_messages = 1000
     for i in range(num_messages):
         flow_instance.run(f"Message {i}")
@@ -997,16 +1113,21 @@ def test_flow_complex_use_case(flow_instance):
     flow_instance.add_context("user_id", "12345")
     flow_instance.run("Hello")
     flow_instance.run("How can I help you?")
-    assert flow_instance.get_response() == "Please provide more details."
+    assert (
+        flow_instance.get_response() == "Please provide more details."
+    )
     flow_instance.update_context("user_id", "54321")
     flow_instance.run("I need help with my order")
-    assert flow_instance.get_response() == "Sure, I can assist with that."
+    assert (
+        flow_instance.get_response()
+        == "Sure, I can assist with that."
+    )
     flow_instance.reset_conversation()
     assert len(flow_instance.get_message_history()) == 0
     assert flow_instance.get_context("user_id") is None
 
 
-# Add more test cases as needed to cover various aspects of your Flow class
+# Add more test cases as needed to cover various aspects of your Agent class
 def test_flow_context_handling(flow_instance):
     # Test context handling
     flow_instance.add_context("user_id", "12345")
@@ -1039,7 +1160,9 @@ def test_flow_concurrent_requests(flow_instance):
 
 def test_flow_custom_timeout(flow_instance):
     # Test custom timeout handling
-    flow_instance.set_timeout(10)  # Set a custom timeout of 10 seconds
+    flow_instance.set_timeout(
+        10
+    )  # Set a custom timeout of 10 seconds
     assert flow_instance.get_timeout() == 10
 
     import time
@@ -1051,7 +1174,7 @@ def test_flow_custom_timeout(flow_instance):
     assert execution_time >= 10  # Ensure the timeout was respected
 
 
-# Add more test cases as needed to thoroughly cover your Flow class
+# Add more test cases as needed to thoroughly cover your Agent class
 
 
 def test_flow_interactive_run(flow_instance, capsys):
@@ -1081,7 +1204,7 @@ def test_flow_interactive_run(flow_instance, capsys):
     simulate_user_input(user_input)
 
 
-# Assuming you have already defined your Flow class and created an instance for testing
+# Assuming you have already defined your Agent class and created an instance for testing
 
 
 def test_flow_agent_history_prompt(flow_instance):
@@ -1089,10 +1212,17 @@ def test_flow_agent_history_prompt(flow_instance):
     system_prompt = "This is the system prompt."
     history = ["User: Hi", "AI: Hello"]
 
-    agent_history_prompt = flow_instance.agent_history_prompt(system_prompt, history)
+    agent_history_prompt = flow_instance.agent_history_prompt(
+        system_prompt, history
+    )
 
-    assert "SYSTEM_PROMPT: This is the system prompt." in agent_history_prompt
-    assert "History: ['User: Hi', 'AI: Hello']" in agent_history_prompt
+    assert (
+        "SYSTEM_PROMPT: This is the system prompt."
+        in agent_history_prompt
+    )
+    assert (
+        "History: ['User: Hi', 'AI: Hello']" in agent_history_prompt
+    )
 
 
 async def test_flow_run_concurrent(flow_instance):
@@ -1120,34 +1250,40 @@ def test_flow_bulk_run(flow_instance):
 
 
 def test_flow_from_llm_and_template():
-    # Test creating Flow instance from an LLM and a template
+    # Test creating Agent instance from an LLM and a template
     llm_instance = mocked_llm  # Replace with your LLM class
     template = "This is a template for testing."
 
-    flow_instance = Flow.from_llm_and_template(llm_instance, template)
+    flow_instance = Agent.from_llm_and_template(
+        llm_instance, template
+    )
 
-    assert isinstance(flow_instance, Flow)
+    assert isinstance(flow_instance, Agent)
 
 
 def test_flow_from_llm_and_template_file():
-    # Test creating Flow instance from an LLM and a template file
+    # Test creating Agent instance from an LLM and a template file
     llm_instance = mocked_llm  # Replace with your LLM class
-    template_file = "template.txt"  # Create a template file for testing
+    template_file = (  # Create a template file for testing
+        "template.txt"
+    )
 
-    flow_instance = Flow.from_llm_and_template_file(llm_instance, template_file)
+    flow_instance = Agent.from_llm_and_template_file(
+        llm_instance, template_file
+    )
 
-    assert isinstance(flow_instance, Flow)
+    assert isinstance(flow_instance, Agent)
 
 
 def test_flow_save_and_load(flow_instance, tmp_path):
-    # Test saving and loading the flow state
+    # Test saving and loading the agent state
     file_path = tmp_path / "flow_state.json"
 
     # Save the state
     flow_instance.save(file_path)
 
     # Create a new instance and load the state
-    new_flow_instance = Flow(llm=mocked_llm, max_loops=5)
+    new_flow_instance = Agent(llm=mocked_llm, max_loops=5)
     new_flow_instance.load(file_path)
 
     # Ensure that the loaded state matches the original state
@@ -1163,22 +1299,22 @@ def test_flow_validate_response(flow_instance):
     assert flow_instance.validate_response(invalid_response) is False
 
 
-# Add more test cases as needed for other methods and features of your Flow class
+# Add more test cases as needed for other methods and features of your Agent class
 
 # Finally, don't forget to run your tests using a testing framework like pytest
 
-# Assuming you have already defined your Flow class and created an instance for testing
+# Assuming you have already defined your Agent class and created an instance for testing
 
 
 def test_flow_print_history_and_memory(capsys, flow_instance):
-    # Test printing the history and memory of the flow
+    # Test printing the history and memory of the agent
     history = ["User: Hi", "AI: Hello"]
     flow_instance.memory = [history]
 
     flow_instance.print_history_and_memory()
 
     captured = capsys.readouterr()
-    assert "Flow History and Memory" in captured.out
+    assert "Agent History and Memory" in captured.out
     assert "Loop 1:" in captured.out
     assert "User: Hi" in captured.out
     assert "AI: Hello" in captured.out
@@ -1193,6 +1329,6 @@ def test_flow_run_with_timeout(flow_instance):
     assert response in ["Actual Response", "Timeout"]
 
 
-# Add more test cases as needed for other methods and features of your Flow class
+# Add more test cases as needed for other methods and features of your Agent class
 
 # Finally, don't forget to run your tests using a testing framework like pytest
diff --git a/tests/structs/test_autoscaler.py b/tests/structs/test_autoscaler.py
new file mode 100644
index 00000000..cfb9560e
--- /dev/null
+++ b/tests/structs/test_autoscaler.py
@@ -0,0 +1,140 @@
+import os
+
+from dotenv import load_dotenv
+from pytest import patch
+
+from swarms.models import OpenAIChat
+from swarms.structs import Agent
+from swarms.structs.autoscaler import AutoScaler
+
+load_dotenv()
+
+api_key = os.environ.get("OPENAI_API_KEY")
+llm = OpenAIChat(
+    temperature=0.5,
+    openai_api_key=api_key,
+)
+agent = Agent(llm=llm, max_loops=1)
+
+
+def test_autoscaler_init():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    assert autoscaler.initial_agents == 5
+    assert autoscaler.scale_up_factor == 1
+    assert autoscaler.idle_threshold == 0.2
+    assert autoscaler.busy_threshold == 0.7
+    assert autoscaler.autoscale == True
+    assert autoscaler.min_agents == 1
+    assert autoscaler.max_agents == 5
+    assert autoscaler.custom_scale_strategy == None
+    assert len(autoscaler.agents_pool) == 5
+    assert autoscaler.task_queue.empty() == True
+
+
+def test_autoscaler_add_task():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.add_task("task1")
+    assert autoscaler.task_queue.empty() == False
+
+
+def test_autoscaler_run():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    out = autoscaler.run(
+        agent.id,
+        "Generate a 10,000 word blog on health and wellness.",
+    )
+    assert (
+        out == "Generate a 10,000 word blog on health and wellness."
+    )
+
+
+def test_autoscaler_add_agent():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.add_agent(agent)
+    assert len(autoscaler.agents_pool) == 6
+
+
+def test_autoscaler_remove_agent():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.remove_agent(agent)
+    assert len(autoscaler.agents_pool) == 4
+
+
+def test_autoscaler_get_agent():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    agent = autoscaler.get_agent()
+    assert isinstance(agent, Agent)
+
+
+def test_autoscaler_get_agent_by_id():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    agent = autoscaler.get_agent_by_id(agent.id)
+    assert isinstance(agent, Agent)
+
+
+def test_autoscaler_get_agent_by_id_not_found():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    agent = autoscaler.get_agent_by_id("fake_id")
+    assert agent == None
+
+
+@patch("swarms.swarms.Agent.is_healthy")
+def test_autoscaler_check_agent_health(mock_is_healthy):
+    mock_is_healthy.side_effect = [False, True, True, True, True]
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.check_agent_health()
+    assert mock_is_healthy.call_count == 5
+
+
+def test_autoscaler_balance_load():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.add_task("task1")
+    autoscaler.add_task("task2")
+    autoscaler.balance_load()
+    assert autoscaler.task_queue.empty()
+
+
+def test_autoscaler_set_scaling_strategy():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+
+    def strategy(x, y):
+        return x - y
+
+    autoscaler.set_scaling_strategy(strategy)
+    assert autoscaler.custom_scale_strategy == strategy
+
+
+def test_autoscaler_execute_scaling_strategy():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+
+    def strategy(x, y):
+        return x - y
+
+    autoscaler.set_scaling_strategy(strategy)
+    autoscaler.add_task("task1")
+    autoscaler.execute_scaling_strategy()
+    assert len(autoscaler.agents_pool) == 4
+
+
+def test_autoscaler_report_agent_metrics():
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    metrics = autoscaler.report_agent_metrics()
+    assert set(metrics.keys()) == {
+        "completion_time",
+        "success_rate",
+        "error_rate",
+    }
+
+
+@patch("swarms.swarms.AutoScaler.report_agent_metrics")
+def test_autoscaler_report(mock_report_agent_metrics):
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.report()
+    mock_report_agent_metrics.assert_called_once()
+
+
+@patch("builtins.print")
+def test_autoscaler_print_dashboard(mock_print):
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
+    autoscaler.print_dashboard()
+    mock_print.assert_called()
diff --git a/tests/structs/sequential_workflow.py b/tests/structs/test_sequential_workflow.py
similarity index 93%
rename from tests/structs/sequential_workflow.py
rename to tests/structs/test_sequential_workflow.py
index 103711de..0d12991a 100644
--- a/tests/structs/sequential_workflow.py
+++ b/tests/structs/test_sequential_workflow.py
@@ -5,8 +5,11 @@ from unittest.mock import patch
 import pytest
 
 from swarms.models import OpenAIChat
-from swarms.structs.flow import Flow
-from swarms.structs.sequential_workflow import SequentialWorkflow, Task
+from swarms.structs.agent import Agent
+from swarms.structs.sequential_workflow import (
+    SequentialWorkflow,
+    Task,
+)
 
 # Mock the OpenAI API key using environment variables
 os.environ["OPENAI_API_KEY"] = "mocked_api_key"
@@ -21,8 +24,8 @@ class MockOpenAIChat:
         return "Mocked result"
 
 
-# Mock Flow class for testing
-class MockFlow:
+# Mock Agent class for testing
+class MockAgent:
     def __init__(self, *args, **kwargs):
         pass
 
@@ -45,16 +48,16 @@ class MockSequentialWorkflow:
 # Test Task class
 def test_task_initialization():
     description = "Sample Task"
-    flow = MockOpenAIChat()
-    task = Task(description=description, flow=flow)
+    agent = MockOpenAIChat()
+    task = Task(description=description, agent=agent)
     assert task.description == description
-    assert task.flow == flow
+    assert task.agent == agent
 
 
 def test_task_execute():
     description = "Sample Task"
-    flow = MockOpenAIChat()
-    task = Task(description=description, flow=flow)
+    agent = MockOpenAIChat()
+    task = Task(description=description, agent=agent)
     task.execute()
     assert task.result == "Mocked result"
 
@@ -66,7 +69,10 @@ def test_sequential_workflow_initialization():
     assert len(workflow.tasks) == 0
     assert workflow.max_loops == 1
     assert workflow.autosave is False
-    assert workflow.saved_state_filepath == "sequential_workflow_state.json"
+    assert (
+        workflow.saved_state_filepath
+        == "sequential_workflow_state.json"
+    )
     assert workflow.restore_state_filepath is None
     assert workflow.dashboard is False
 
@@ -78,7 +84,7 @@ def test_sequential_workflow_add_task():
     workflow.add(task_description, task_flow)
     assert len(workflow.tasks) == 1
     assert workflow.tasks[0].description == task_description
-    assert workflow.tasks[0].flow == task_flow
+    assert workflow.tasks[0].agent == task_flow
 
 
 def test_sequential_workflow_reset_workflow():
@@ -169,8 +175,8 @@ def test_sequential_workflow_workflow_dashboard(capfd):
     assert "Sequential Workflow Dashboard" in out
 
 
-# Mock Flow class for async testing
-class MockAsyncFlow:
+# Mock Agent class for async testing
+class MockAsyncAgent:
     def __init__(self, *args, **kwargs):
         pass
 
@@ -183,7 +189,7 @@ class MockAsyncFlow:
 async def test_sequential_workflow_arun():
     workflow = SequentialWorkflow()
     task_description = "Sample Task"
-    task_flow = MockAsyncFlow()
+    task_flow = MockAsyncAgent()
     workflow.add(task_description, task_flow)
     await workflow.arun()
     assert workflow.tasks[0].result == "Mocked result"
@@ -196,9 +202,9 @@ def test_real_world_usage_with_openai_key():
 
 
 def test_real_world_usage_with_flow_and_openai_key():
-    # Initialize a flow with the language model
-    flow = Flow(llm=OpenAIChat())
-    assert isinstance(flow, Flow)
+    # Initialize a agent with the language model
+    agent = Agent(llm=OpenAIChat())
+    assert isinstance(agent, Agent)
 
 
 def test_real_world_usage_with_sequential_workflow():
diff --git a/tests/structs/test_task.py b/tests/structs/test_task.py
new file mode 100644
index 00000000..5db822d4
--- /dev/null
+++ b/tests/structs/test_task.py
@@ -0,0 +1,110 @@
+import os
+from unittest.mock import Mock
+
+import pytest
+from dotenv import load_dotenv
+
+from swarms.models.gpt4_vision_api import GPT4VisionAPI
+from swarms.prompts.multi_modal_autonomous_instruction_prompt import (
+    MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
+)
+from swarms.structs.agent import Agent
+from swarms.structs.task import Task
+
+load_dotenv()
+
+
+@pytest.fixture
+def llm():
+    return GPT4VisionAPI()
+
+
+def test_agent_run_task(llm):
+    task = (
+        "Analyze this image of an assembly line and identify any"
+        " issues such as misaligned parts, defects, or deviations"
+        " from the standard assembly process. IF there is anything"
+        " unsafe in the image, explain why it is unsafe and how it"
+        " could be improved."
+    )
+    img = "assembly_line.jpg"
+
+    agent = Agent(
+        llm=llm,
+        max_loops="auto",
+        sop=MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1,
+        dashboard=True,
+    )
+
+    result = agent.run(task=task, img=img)
+
+    # Add assertions here to verify the expected behavior of the agent's run method
+    assert isinstance(result, dict)
+    assert "response" in result
+    assert "dashboard_data" in result
+    # Add more assertions as needed
+
+
+@pytest.fixture
+def task():
+    agents = [Agent(llm=llm, id=f"Agent_{i}") for i in range(5)]
+    return Task(
+        id="Task_1", task="Task_Name", agents=agents, dependencies=[]
+    )
+
+
+# Basic tests
+
+
+def test_task_init(task):
+    assert task.id == "Task_1"
+    assert task.task == "Task_Name"
+    assert isinstance(task.agents, list)
+    assert len(task.agents) == 5
+    assert isinstance(task.dependencies, list)
+
+
+def test_task_execute(task, mocker):
+    mocker.patch.object(Agent, "run", side_effect=[1, 2, 3, 4, 5])
+    parent_results = {}
+    task.execute(parent_results)
+    assert isinstance(task.results, list)
+    assert len(task.results) == 5
+    for result in task.results:
+        assert isinstance(result, int)
+
+
+# Parameterized tests
+
+
+@pytest.mark.parametrize("num_agents", [1, 3, 5, 10])
+def test_task_num_agents(task, num_agents, mocker):
+    task.agents = [Agent(id=f"Agent_{i}") for i in range(num_agents)]
+    mocker.patch.object(Agent, "run", return_value=1)
+    parent_results = {}
+    task.execute(parent_results)
+    assert len(task.results) == num_agents
+
+
+# Exception testing
+
+
+def test_task_execute_with_dependency_error(task, mocker):
+    task.dependencies = ["NonExistentTask"]
+    mocker.patch.object(Agent, "run", return_value=1)
+    parent_results = {}
+    with pytest.raises(KeyError):
+        task.execute(parent_results)
+
+
+# Mocking and monkeypatching tests
+
+
+def test_task_execute_with_mocked_agents(task, mocker):
+    mock_agents = [Mock(spec=Agent) for _ in range(5)]
+    mocker.patch.object(task, "agents", mock_agents)
+    for mock_agent in mock_agents:
+        mock_agent.run.return_value = 1
+    parent_results = {}
+    task.execute(parent_results)
+    assert len(task.results) == 5
diff --git a/tests/structs/workflow.py b/tests/structs/workflow.py
deleted file mode 100644
index fdc6e85e..00000000
--- a/tests/structs/workflow.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from unittest.mock import patch, MagicMock
-from swarms.structs.workflow import Workflow
-
-
-def test_workflow_initialization():
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    assert isinstance(workflow, Workflow)
-    assert workflow.agent == agent
-    assert workflow.tasks == []
-    assert workflow.parallel is False
-
-
-def test_workflow_add():
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    task = workflow.add("What's the weather in miami")
-    assert isinstance(task, Workflow.Task)
-    assert task.task == "What's the weather in miami"
-    assert task.parents == []
-    assert task.children == []
-    assert task.output is None
-    assert task.structure == workflow
-
-
-def test_workflow_first_task():
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    assert workflow.first_task() is None
-    workflow.add("What's the weather in miami")
-    assert workflow.first_task().task == "What's the weather in miami"
-
-
-def test_workflow_last_task():
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    assert workflow.last_task() is None
-    workflow.add("What's the weather in miami")
-    assert workflow.last_task().task == "What's the weather in miami"
-
-
-@patch("your_module.Workflow.__run_from_task")
-def test_workflow_run(mock_run_from_task):
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    workflow.add("What's the weather in miami")
-    workflow.run()
-    mock_run_from_task.assert_called_once()
-
-
-def test_workflow_context():
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    task = workflow.add("What's the weather in miami")
-    assert workflow.context(task) == {
-        "parent_output": None,
-        "parent": None,
-        "child": None,
-    }
-
-
-@patch("your_module.Workflow.Task.execute")
-def test_workflow___run_from_task(mock_execute):
-    agent = MagicMock()
-    workflow = Workflow(agent)
-    task = workflow.add("What's the weather in miami")
-    mock_execute.return_value = "Sunny"
-    workflow.__run_from_task(task)
-    mock_execute.assert_called_once()
diff --git a/tests/swarms/multi_agent_debate.py b/tests/swarms/multi_agent_debate.py
deleted file mode 100644
index a2687f54..00000000
--- a/tests/swarms/multi_agent_debate.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from unittest.mock import patch
-from swarms.swarms.multi_agent_debate import MultiAgentDebate, Worker, select_speaker
-
-
-def test_multiagentdebate_initialization():
-    multiagentdebate = MultiAgentDebate(
-        agents=[Worker] * 5, selection_func=select_speaker
-    )
-    assert isinstance(multiagentdebate, MultiAgentDebate)
-    assert len(multiagentdebate.agents) == 5
-    assert multiagentdebate.selection_func == select_speaker
-
-
-@patch("swarms.workers.Worker.reset")
-def test_multiagentdebate_reset_agents(mock_reset):
-    multiagentdebate = MultiAgentDebate(
-        agents=[Worker] * 5, selection_func=select_speaker
-    )
-    multiagentdebate.reset_agents()
-    assert mock_reset.call_count == 5
-
-
-def test_multiagentdebate_inject_agent():
-    multiagentdebate = MultiAgentDebate(
-        agents=[Worker] * 5, selection_func=select_speaker
-    )
-    multiagentdebate.inject_agent(Worker)
-    assert len(multiagentdebate.agents) == 6
-
-
-@patch("swarms.workers.Worker.run")
-def test_multiagentdebate_run(mock_run):
-    multiagentdebate = MultiAgentDebate(
-        agents=[Worker] * 5, selection_func=select_speaker
-    )
-    results = multiagentdebate.run("Write a short story.")
-    assert len(results) == 5
-    assert mock_run.call_count == 5
-
-
-def test_multiagentdebate_update_task():
-    multiagentdebate = MultiAgentDebate(
-        agents=[Worker] * 5, selection_func=select_speaker
-    )
-    multiagentdebate.update_task("Write a short story.")
-    assert multiagentdebate.task == "Write a short story."
-
-
-def test_multiagentdebate_format_results():
-    multiagentdebate = MultiAgentDebate(
-        agents=[Worker] * 5, selection_func=select_speaker
-    )
-    results = [
-        {"agent": "Agent 1", "response": "Hello, world!"},
-        {"agent": "Agent 2", "response": "Goodbye, world!"},
-    ]
-    formatted_results = multiagentdebate.format_results(results)
-    assert (
-        formatted_results
-        == "Agent Agent 1 responded: Hello, world!\nAgent Agent 2 responded: Goodbye, world!"
-    )
diff --git a/tests/swarms/autoscaler.py b/tests/swarms/test_autoscaler.py
similarity index 77%
rename from tests/swarms/autoscaler.py
rename to tests/swarms/test_autoscaler.py
index e8a719c7..fbf63637 100644
--- a/tests/swarms/autoscaler.py
+++ b/tests/swarms/test_autoscaler.py
@@ -1,11 +1,11 @@
 from unittest.mock import patch
 from swarms.structs.autoscaler import AutoScaler
 from swarms.models import OpenAIChat
-from swarms.structs import Flow
+from swarms.structs import Agent
 
 llm = OpenAIChat()
 
-flow = Flow(
+agent = Agent(
     llm=llm,
     max_loops=2,
     dashboard=True,
@@ -18,7 +18,7 @@ def test_autoscaler_initialization():
         scale_up_factor=2,
         idle_threshold=0.1,
         busy_threshold=0.8,
-        agent=flow,
+        agent=agent,
     )
     assert isinstance(autoscaler, AutoScaler)
     assert autoscaler.scale_up_factor == 2
@@ -28,19 +28,21 @@ def test_autoscaler_initialization():
 
 
 def test_autoscaler_add_task():
-    autoscaler = AutoScaler(agent=flow)
+    autoscaler = AutoScaler(agent=agent)
     autoscaler.add_task("task1")
     assert autoscaler.task_queue.qsize() == 1
 
 
 def test_autoscaler_scale_up():
-    autoscaler = AutoScaler(initial_agents=5, scale_up_factor=2, agent=flow)
+    autoscaler = AutoScaler(
+        initial_agents=5, scale_up_factor=2, agent=agent
+    )
     autoscaler.scale_up()
     assert len(autoscaler.agents_pool) == 10
 
 
 def test_autoscaler_scale_down():
-    autoscaler = AutoScaler(initial_agents=5, agent=flow)
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
     autoscaler.scale_down()
     assert len(autoscaler.agents_pool) == 4
 
@@ -48,7 +50,7 @@ def test_autoscaler_scale_down():
 @patch("swarms.swarms.AutoScaler.scale_up")
 @patch("swarms.swarms.AutoScaler.scale_down")
 def test_autoscaler_monitor_and_scale(mock_scale_down, mock_scale_up):
-    autoscaler = AutoScaler(initial_agents=5, agent=flow)
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
     autoscaler.add_task("task1")
     autoscaler.monitor_and_scale()
     mock_scale_up.assert_called_once()
@@ -56,9 +58,9 @@ def test_autoscaler_monitor_and_scale(mock_scale_down, mock_scale_up):
 
 
 @patch("swarms.swarms.AutoScaler.monitor_and_scale")
-@patch("swarms.swarms.flow.run")
+@patch("swarms.swarms.agent.run")
 def test_autoscaler_start(mock_run, mock_monitor_and_scale):
-    autoscaler = AutoScaler(initial_agents=5, agent=flow)
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
     autoscaler.add_task("task1")
     autoscaler.start()
     mock_run.assert_called_once()
@@ -66,6 +68,6 @@ def test_autoscaler_start(mock_run, mock_monitor_and_scale):
 
 
 def test_autoscaler_del_agent():
-    autoscaler = AutoScaler(initial_agents=5, agent=flow)
+    autoscaler = AutoScaler(initial_agents=5, agent=agent)
     autoscaler.del_agent()
     assert len(autoscaler.agents_pool) == 4
diff --git a/tests/swarms/dialogue_simulator.py b/tests/swarms/test_dialogue_simulator.py
similarity index 88%
rename from tests/swarms/dialogue_simulator.py
rename to tests/swarms/test_dialogue_simulator.py
index 52cd6367..40665201 100644
--- a/tests/swarms/dialogue_simulator.py
+++ b/tests/swarms/test_dialogue_simulator.py
@@ -11,7 +11,9 @@ def test_dialoguesimulator_initialization():
 @patch("swarms.workers.worker.Worker.run")
 def test_dialoguesimulator_run(mock_run):
     dialoguesimulator = DialogueSimulator(agents=[Worker] * 5)
-    dialoguesimulator.run(max_iters=5, name="Agent 1", message="Hello, world!")
+    dialoguesimulator.run(
+        max_iters=5, name="Agent 1", message="Hello, world!"
+    )
     assert mock_run.call_count == 30
 
 
diff --git a/tests/swarms/godmode.py b/tests/swarms/test_godmode.py
similarity index 85%
rename from tests/swarms/godmode.py
rename to tests/swarms/test_godmode.py
index fa9e0c13..8f528026 100644
--- a/tests/swarms/godmode.py
+++ b/tests/swarms/test_godmode.py
@@ -16,7 +16,13 @@ def test_godmode_run(monkeypatch):
     godmode = GodMode(llms=[LLM] * 5)
     responses = godmode.run("task1")
     assert len(responses) == 5
-    assert responses == ["response", "response", "response", "response", "response"]
+    assert responses == [
+        "response",
+        "response",
+        "response",
+        "response",
+        "response",
+    ]
 
 
 @patch("builtins.print")
diff --git a/tests/swarms/groupchat.py b/tests/swarms/test_groupchat.py
similarity index 92%
rename from tests/swarms/groupchat.py
rename to tests/swarms/test_groupchat.py
index b25e7f91..ce17a4d2 100644
--- a/tests/swarms/groupchat.py
+++ b/tests/swarms/test_groupchat.py
@@ -2,7 +2,7 @@ import pytest
 
 from swarms.models import OpenAIChat
 from swarms.models.anthropic import Anthropic
-from swarms.structs.flow import Flow
+from swarms.structs.agent import Agent
 from swarms.swarms.groupchat import GroupChat, GroupChatManager
 
 llm = OpenAIChat()
@@ -21,12 +21,12 @@ class MockOpenAI:
 # Create fixtures for agents and a sample message
 @pytest.fixture
 def agent1():
-    return Flow(name="Agent1", llm=llm)
+    return Agent(name="Agent1", llm=llm)
 
 
 @pytest.fixture
 def agent2():
-    return Flow(name="Agent2", llm=llm2)
+    return Agent(name="Agent2", llm=llm2)
 
 
 @pytest.fixture
@@ -155,7 +155,7 @@ def test_groupchat_manager_generate_reply():
 
 # Test case to ensure GroupChat selects the next speaker correctly
 def test_groupchat_select_speaker():
-    agent3 = Flow(name="agent3", llm=llm)
+    agent3 = Agent(name="agent3", llm=llm)
     agents = [agent1, agent2, agent3]
     groupchat = GroupChat(agents=agents, messages=[], max_round=10)
 
@@ -165,7 +165,9 @@ def test_groupchat_select_speaker():
 
     # Simulate selecting the next speaker
     last_speaker = agent1
-    next_speaker = manager.select_speaker(last_speaker=last_speaker, selector=selector)
+    next_speaker = manager.select_speaker(
+        last_speaker=last_speaker, selector=selector
+    )
 
     # Ensure the next speaker is agent2
     assert next_speaker == agent2
@@ -173,7 +175,7 @@ def test_groupchat_select_speaker():
 
 # Test case to ensure GroupChat handles underpopulated group correctly
 def test_groupchat_underpopulated_group():
-    agent1 = Flow(name="agent1", llm=llm)
+    agent1 = Agent(name="agent1", llm=llm)
     agents = [agent1]
     groupchat = GroupChat(agents=agents, messages=[], max_round=10)
 
@@ -183,7 +185,9 @@ def test_groupchat_underpopulated_group():
 
     # Simulate selecting the next speaker in an underpopulated group
     last_speaker = agent1
-    next_speaker = manager.select_speaker(last_speaker=last_speaker, selector=selector)
+    next_speaker = manager.select_speaker(
+        last_speaker=last_speaker, selector=selector
+    )
 
     # Ensure the next speaker is the same as the last speaker in an underpopulated group
     assert next_speaker == last_speaker
@@ -207,7 +211,9 @@ def test_groupchat_max_rounds():
         last_speaker = next_speaker
 
     # Try one more round, should stay with the last speaker
-    next_speaker = manager.select_speaker(last_speaker=last_speaker, selector=selector)
+    next_speaker = manager.select_speaker(
+        last_speaker=last_speaker, selector=selector
+    )
 
     # Ensure the next speaker is the same as the last speaker after reaching max rounds
     assert next_speaker == last_speaker
diff --git a/tests/swarms/multi_agent_collab.py b/tests/swarms/test_multi_agent_collab.py
similarity index 89%
rename from tests/swarms/multi_agent_collab.py
rename to tests/swarms/test_multi_agent_collab.py
index 3f7a0729..e30358aa 100644
--- a/tests/swarms/multi_agent_collab.py
+++ b/tests/swarms/test_multi_agent_collab.py
@@ -2,7 +2,7 @@ import json
 import os
 import pytest
 from unittest.mock import Mock
-from swarms.structs import Flow
+from swarms.structs import Agent
 from swarms.models import OpenAIChat
 from swarms.swarms.multi_agent_collab import (
     MultiAgentCollaboration,
@@ -11,8 +11,8 @@ from swarms.swarms.multi_agent_collab import (
 )
 
 # Sample agents for testing
-agent1 = Flow(llm=OpenAIChat(), max_loops=2)
-agent2 = Flow(llm=OpenAIChat(), max_loops=2)
+agent1 = Agent(llm=OpenAIChat(), max_loops=2)
+agent2 = Agent(llm=OpenAIChat(), max_loops=2)
 agents = [agent1, agent2]
 
 
@@ -43,7 +43,7 @@ def test_inject(collaboration):
 
 
 def test_inject_agent(collaboration):
-    agent3 = Flow(llm=OpenAIChat(), max_loops=2)
+    agent3 = Agent(llm=OpenAIChat(), max_loops=2)
     collaboration.inject_agent(agent3)
     assert len(collaboration.agents) == 3
     assert agent3 in collaboration.agents
@@ -75,8 +75,12 @@ def test_run(collaboration):
 
 
 def test_format_results(collaboration):
-    collaboration.results = [{"agent": "Agent1", "response": "Response1"}]
-    formatted_results = collaboration.format_results(collaboration.results)
+    collaboration.results = [
+        {"agent": "Agent1", "response": "Response1"}
+    ]
+    formatted_results = collaboration.format_results(
+        collaboration.results
+    )
     assert "Agent1 responded: Response1" in formatted_results
 
 
@@ -115,7 +119,10 @@ def test_repr(collaboration):
 
 
 def test_load(collaboration):
-    state = {"step": 5, "results": [{"agent": "Agent1", "response": "Response1"}]}
+    state = {
+        "step": 5,
+        "results": [{"agent": "Agent1", "response": "Response1"}],
+    }
     with open(collaboration.saved_file_path_name, "w") as file:
         json.dump(state, file)
 
@@ -140,7 +147,8 @@ def test_save(collaboration, tmp_path):
 
 # Example of parameterized test for different selection functions
 @pytest.mark.parametrize(
-    "selection_function", [select_next_speaker_director, select_speaker_round_table]
+    "selection_function",
+    [select_next_speaker_director, select_speaker_round_table],
 )
 def test_selection_functions(collaboration, selection_function):
     collaboration.select_next_speaker = selection_function
diff --git a/tests/swarms/orchestrate.py b/tests/swarms/test_orchestrate.py
similarity index 90%
rename from tests/swarms/orchestrate.py
rename to tests/swarms/test_orchestrate.py
index 7a73d92d..4136ad94 100644
--- a/tests/swarms/orchestrate.py
+++ b/tests/swarms/test_orchestrate.py
@@ -22,10 +22,14 @@ def mock_vector_db():
 def orchestrator(mock_agent, mock_vector_db):
     agent_list = [mock_agent for _ in range(5)]
     task_queue = []
-    return Orchestrator(mock_agent, agent_list, task_queue, mock_vector_db)
+    return Orchestrator(
+        mock_agent, agent_list, task_queue, mock_vector_db
+    )
 
 
-def test_assign_task(orchestrator, mock_agent, mock_task, mock_vector_db):
+def test_assign_task(
+    orchestrator, mock_agent, mock_task, mock_vector_db
+):
     orchestrator.task_queue.append(mock_task)
     orchestrator.assign_task(0, mock_task)
 
diff --git a/tests/swarms/simple_swarm.py b/tests/swarms/test_simple_swarm.py
similarity index 100%
rename from tests/swarms/simple_swarm.py
rename to tests/swarms/test_simple_swarm.py
diff --git a/tests/tools/base.py b/tests/tools/test_base.py
similarity index 94%
rename from tests/tools/base.py
rename to tests/tools/test_base.py
index 4f7e2b4b..9f9c700f 100644
--- a/tests/tools/base.py
+++ b/tests/tools/test_base.py
@@ -3,7 +3,13 @@ from unittest.mock import MagicMock
 import pytest
 from pydantic import BaseModel
 
-from swarms.tools.tool import BaseTool, Runnable, StructuredTool, Tool, tool
+from swarms.tools.tool import (
+    BaseTool,
+    Runnable,
+    StructuredTool,
+    Tool,
+    tool,
+)
 
 # Define test data
 test_input = {"key1": "value1", "key2": "value2"}
@@ -59,14 +65,18 @@ def test_structured_tool_invoke():
 
 
 def test_tool_creation():
-    tool = Tool(name="test_tool", func=lambda x: x, description="Test tool")
+    tool = Tool(
+        name="test_tool", func=lambda x: x, description="Test tool"
+    )
     assert tool.name == "test_tool"
     assert tool.func is not None
     assert tool.description == "Test tool"
 
 
 def test_tool_ainvoke():
-    tool = Tool(name="test_tool", func=lambda x: x, description="Test tool")
+    tool = Tool(
+        name="test_tool", func=lambda x: x, description="Test tool"
+    )
     result = tool.ainvoke("input_data")
     assert result == "input_data"
 
@@ -75,7 +85,11 @@ def test_tool_ainvoke_with_coroutine():
     async def async_function(input_data):
         return input_data
 
-    tool = Tool(name="test_tool", coroutine=async_function, description="Test tool")
+    tool = Tool(
+        name="test_tool",
+        coroutine=async_function,
+        description="Test tool",
+    )
     result = tool.ainvoke("input_data")
     assert result == "input_data"
 
@@ -84,7 +98,11 @@ def test_tool_args():
     def sample_function(input_data):
         return input_data
 
-    tool = Tool(name="test_tool", func=sample_function, description="Test tool")
+    tool = Tool(
+        name="test_tool",
+        func=sample_function,
+        description="Test tool",
+    )
     assert tool.args == {"tool_input": {"type": "string"}}
 
 
@@ -164,7 +182,9 @@ def test_tool_ainvoke_exception():
 
 
 def test_tool_ainvoke_with_coroutine_exception():
-    tool = Tool(name="test_tool", coroutine=None, description="Test tool")
+    tool = Tool(
+        name="test_tool", coroutine=None, description="Test tool"
+    )
     with pytest.raises(NotImplementedError):
         tool.ainvoke("input_data")
 
@@ -287,7 +307,9 @@ def test_structured_tool_ainvoke_with_callbacks():
         args_schema=SampleArgsSchema,
     )
     callbacks = MagicMock()
-    result = tool.ainvoke({"tool_input": "input_data"}, callbacks=callbacks)
+    result = tool.ainvoke(
+        {"tool_input": "input_data"}, callbacks=callbacks
+    )
     assert result == "input_data"
     callbacks.on_start.assert_called_once()
     callbacks.on_finish.assert_called_once()
@@ -347,7 +369,9 @@ def test_structured_tool_ainvoke_with_new_argument():
         func=sample_function,
         args_schema=SampleArgsSchema,
     )
-    result = tool.ainvoke({"tool_input": "input_data"}, callbacks=None)
+    result = tool.ainvoke(
+        {"tool_input": "input_data"}, callbacks=None
+    )
     assert result == "input_data"
 
 
@@ -459,7 +483,9 @@ def test_tool_with_runnable(mock_runnable):
 def test_tool_with_invalid_argument():
     # Test passing an invalid argument type
     with pytest.raises(ValueError):
-        tool(123)  # Using an integer instead of a string/callable/Runnable
+        tool(
+            123
+        )  # Using an integer instead of a string/callable/Runnable
 
 
 def test_tool_with_multiple_arguments(mock_func):
@@ -521,7 +547,9 @@ class MockSchema(BaseModel):
 # Test suite starts here
 class TestTool:
     # Basic Functionality Tests
-    def test_tool_with_valid_callable_creates_base_tool(self, mock_func):
+    def test_tool_with_valid_callable_creates_base_tool(
+        self, mock_func
+    ):
         result = tool(mock_func)
         assert isinstance(result, BaseTool)
 
@@ -560,7 +588,9 @@ class TestTool:
         with pytest.raises(ValueError):
             tool(no_doc_func)
 
-    def test_tool_raises_error_runnable_without_object_schema(self, mock_runnable):
+    def test_tool_raises_error_runnable_without_object_schema(
+        self, mock_runnable
+    ):
         with pytest.raises(ValueError):
             tool(mock_runnable)
 
@@ -779,7 +809,9 @@ class TestTool:
         def thread_target():
             results.append(threaded_function(5))
 
-        threads = [threading.Thread(target=thread_target) for _ in range(10)]
+        threads = [
+            threading.Thread(target=thread_target) for _ in range(10)
+        ]
         for t in threads:
             t.start()
         for t in threads:
diff --git a/tests/upload_tests_to_issues b/tests/upload_tests_to_issues
new file mode 100644
index 00000000..cc2392e3
--- /dev/null
+++ b/tests/upload_tests_to_issues
@@ -0,0 +1,58 @@
+import os
+import subprocess
+import json
+import re
+import requests
+from dotenv import load_dotenv
+
+load_dotenv
+
+# Constants
+GITHUB_USERNAME = os.getenv('GITHUB_USERNAME')
+REPO_NAME = os.getenv('GITHUB_REPO_NAME')
+GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
+ISSUES_URL = f'https://api.github.com/repos/{GITHUB_USERNAME}/{REPO_NAME}/issues'
+
+# Headers for authentication
+headers = {
+    'Authorization': f'token {GITHUB_TOKEN}',
+    'Accept': 'application/vnd.github.v3+json'
+}
+
+def run_pytest():
+    result = subprocess.run(['pytest'], capture_output=True, text=True)
+    return result.stdout + result.stderr
+
+def parse_pytest_output(output):
+    errors = []
+    current_error = None
+
+    for line in output.split('\n'):
+        if line.startswith('_________________________'):
+            if current_error:
+                errors.append(current_error)
+            current_error = {'title': '', 'body': ''}
+        elif current_error is not None:
+            if not current_error['title']:
+                current_error['title'] = line.strip()
+            current_error['body'] += line + '\n'
+
+    if current_error:
+        errors.append(current_error)
+    return errors
+
+def create_github_issue(title, body):
+    issue = {'title': title, 'body': body}
+    response = requests.post(ISSUES_URL, headers=headers, json=issue)
+    return response.json()
+
+def main():
+    pytest_output = run_pytest()
+    errors = parse_pytest_output(pytest_output)
+    
+    for error in errors:
+        issue_response = create_github_issue(error['title'], error['body'])
+        print(f"Issue created: {issue_response.get('html_url')}")
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/utils/subprocess_code_interpreter.py b/tests/utils/test_subprocess_code_interpreter.py
similarity index 71%
rename from tests/utils/subprocess_code_interpreter.py
rename to tests/utils/test_subprocess_code_interpreter.py
index ab7c748f..2c7f7e47 100644
--- a/tests/utils/subprocess_code_interpreter.py
+++ b/tests/utils/test_subprocess_code_interpreter.py
@@ -4,7 +4,10 @@ import time
 
 import pytest
 
-from swarms.utils.code_interpreter import BaseCodeInterpreter, SubprocessCodeInterpreter
+from swarms.utils.code_interpreter import (
+    BaseCodeInterpreter,
+    SubprocessCodeInterpreter,
+)
 
 
 @pytest.fixture
@@ -32,39 +35,62 @@ def test_base_code_interpreter_terminate_not_implemented():
         interpreter.terminate()
 
 
-def test_subprocess_code_interpreter_init(subprocess_code_interpreter):
-    assert isinstance(subprocess_code_interpreter, SubprocessCodeInterpreter)
+def test_subprocess_code_interpreter_init(
+    subprocess_code_interpreter,
+):
+    assert isinstance(
+        subprocess_code_interpreter, SubprocessCodeInterpreter
+    )
 
 
-def test_subprocess_code_interpreter_start_process(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_start_process(
+    subprocess_code_interpreter,
+):
     subprocess_code_interpreter.start_process()
     assert subprocess_code_interpreter.process is not None
 
 
-def test_subprocess_code_interpreter_terminate(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_terminate(
+    subprocess_code_interpreter,
+):
     subprocess_code_interpreter.start_process()
     subprocess_code_interpreter.terminate()
     assert subprocess_code_interpreter.process.poll() is not None
 
 
-def test_subprocess_code_interpreter_run_success(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_run_success(
+    subprocess_code_interpreter,
+):
     code = 'print("Hello, World!")'
     result = list(subprocess_code_interpreter.run(code))
-    assert any("Hello, World!" in output.get("output", "") for output in result)
+    assert any(
+        "Hello, World!" in output.get("output", "")
+        for output in result
+    )
 
 
-def test_subprocess_code_interpreter_run_with_error(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_run_with_error(
+    subprocess_code_interpreter,
+):
     code = 'print("Hello, World")\nraise ValueError("Error!")'
     result = list(subprocess_code_interpreter.run(code))
-    assert any("Error!" in output.get("output", "") for output in result)
+    assert any(
+        "Error!" in output.get("output", "") for output in result
+    )
 
 
 def test_subprocess_code_interpreter_run_with_keyboard_interrupt(
     subprocess_code_interpreter,
 ):
-    code = 'import time\ntime.sleep(2)\nprint("Hello, World")\nraise KeyboardInterrupt'
+    code = (
+        'import time\ntime.sleep(2)\nprint("Hello, World")\nraise'
+        " KeyboardInterrupt"
+    )
     result = list(subprocess_code_interpreter.run(code))
-    assert any("KeyboardInterrupt" in output.get("output", "") for output in result)
+    assert any(
+        "KeyboardInterrupt" in output.get("output", "")
+        for output in result
+    )
 
 
 def test_subprocess_code_interpreter_run_max_retries(
@@ -78,7 +104,8 @@ def test_subprocess_code_interpreter_run_max_retries(
     code = 'print("Hello, World!")'
     result = list(subprocess_code_interpreter.run(code))
     assert any(
-        "Maximum retries reached. Could not execute code." in output.get("output", "")
+        "Maximum retries reached. Could not execute code."
+        in output.get("output", "")
         for output in result
     )
 
@@ -104,7 +131,10 @@ def test_subprocess_code_interpreter_run_retry_on_error(
 
     code = 'print("Hello, World!")'
     result = list(subprocess_code_interpreter.run(code))
-    assert any("Hello, World!" in output.get("output", "") for output in result)
+    assert any(
+        "Hello, World!" in output.get("output", "")
+        for output in result
+    )
 
 
 # Add more tests to cover other aspects of the code and edge cases as needed
@@ -112,19 +142,33 @@ def test_subprocess_code_interpreter_run_retry_on_error(
 # Import statements and fixtures from the previous code block
 
 
-def test_subprocess_code_interpreter_line_postprocessor(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_line_postprocessor(
+    subprocess_code_interpreter,
+):
     line = "This is a test line"
-    processed_line = subprocess_code_interpreter.line_postprocessor(line)
-    assert processed_line == line  # No processing, should remain the same
+    processed_line = subprocess_code_interpreter.line_postprocessor(
+        line
+    )
+    assert (
+        processed_line == line
+    )  # No processing, should remain the same
 
 
-def test_subprocess_code_interpreter_preprocess_code(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_preprocess_code(
+    subprocess_code_interpreter,
+):
     code = 'print("Hello, World!")'
-    preprocessed_code = subprocess_code_interpreter.preprocess_code(code)
-    assert preprocessed_code == code  # No preprocessing, should remain the same
+    preprocessed_code = subprocess_code_interpreter.preprocess_code(
+        code
+    )
+    assert (
+        preprocessed_code == code
+    )  # No preprocessing, should remain the same
 
 
-def test_subprocess_code_interpreter_detect_active_line(subprocess_code_interpreter):
+def test_subprocess_code_interpreter_detect_active_line(
+    subprocess_code_interpreter,
+):
     line = "Active line: 5"
     active_line = subprocess_code_interpreter.detect_active_line(line)
     assert active_line == 5
@@ -134,7 +178,9 @@ def test_subprocess_code_interpreter_detect_end_of_execution(
     subprocess_code_interpreter,
 ):
     line = "Execution completed."
-    end_of_execution = subprocess_code_interpreter.detect_end_of_execution(line)
+    end_of_execution = (
+        subprocess_code_interpreter.detect_end_of_execution(line)
+    )
     assert end_of_execution is True
 
 
@@ -172,7 +218,9 @@ def test_subprocess_code_interpreter_handle_stream_output_stdout(
     subprocess_code_interpreter,
 ):
     line = "This is a test line"
-    subprocess_code_interpreter.handle_stream_output(threading.current_thread(), False)
+    subprocess_code_interpreter.handle_stream_output(
+        threading.current_thread(), False
+    )
     subprocess_code_interpreter.process.stdout.write(line + "\n")
     subprocess_code_interpreter.process.stdout.flush()
     time.sleep(0.1)
@@ -184,7 +232,9 @@ def test_subprocess_code_interpreter_handle_stream_output_stderr(
     subprocess_code_interpreter,
 ):
     line = "This is an error line"
-    subprocess_code_interpreter.handle_stream_output(threading.current_thread(), True)
+    subprocess_code_interpreter.handle_stream_output(
+        threading.current_thread(), True
+    )
     subprocess_code_interpreter.process.stderr.write(line + "\n")
     subprocess_code_interpreter.process.stderr.flush()
     time.sleep(0.1)
@@ -200,19 +250,23 @@ def test_subprocess_code_interpreter_run_with_preprocess_code(
         lambda x: x.upper()
     )  # Modify code in preprocess_code
     result = list(subprocess_code_interpreter.run(code))
-    assert any("Hello, World!" in output.get("output", "") for output in result)
+    assert any(
+        "Hello, World!" in output.get("output", "")
+        for output in result
+    )
 
 
 def test_subprocess_code_interpreter_run_with_exception(
     subprocess_code_interpreter, capsys
 ):
     code = 'print("Hello, World!")'
-    subprocess_code_interpreter.start_cmd = (
-        "nonexistent_command"  # Force an exception during subprocess creation
+    subprocess_code_interpreter.start_cmd = (  # Force an exception during subprocess creation
+        "nonexistent_command"
     )
     result = list(subprocess_code_interpreter.run(code))
     assert any(
-        "Maximum retries reached" in output.get("output", "") for output in result
+        "Maximum retries reached" in output.get("output", "")
+        for output in result
     )
 
 
@@ -227,7 +281,9 @@ def test_subprocess_code_interpreter_run_with_active_line(
 def test_subprocess_code_interpreter_run_with_end_of_execution(
     subprocess_code_interpreter, capsys
 ):
-    code = 'print("Hello, World!")'  # Simple code without active line marker
+    code = (  # Simple code without active line marker
+        'print("Hello, World!")'
+    )
     result = list(subprocess_code_interpreter.run(code))
     assert any(output.get("active_line") is None for output in result)
 
@@ -245,4 +301,7 @@ def test_subprocess_code_interpreter_run_with_unicode_characters(
 ):
     code = 'print("γ“γ‚“γ«γ‘γ―γ€δΈ–η•Œ")'  # Contains unicode characters
     result = list(subprocess_code_interpreter.run(code))
-    assert any("γ“γ‚“γ«γ‘γ―γ€δΈ–η•Œ" in output.get("output", "") for output in result)
+    assert any(
+        "γ“γ‚“γ«γ‘γ―γ€δΈ–η•Œ" in output.get("output", "")
+        for output in result
+    )
diff --git a/tests/workers/multi_model_worker.py b/tests/workers/multi_model_worker.py
deleted file mode 100644
index f011d642..00000000
--- a/tests/workers/multi_model_worker.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import pytest
-from unittest.mock import Mock
-from swarms.agents.multi_modal_agent import (
-    MultiModalVisualAgent,
-    MultiModalVisualAgentTool,
-)
-
-
-@pytest.fixture
-def multimodal_agent():
-    # Mock the MultiModalVisualAgent
-    mock_agent = Mock(spec=MultiModalVisualAgent)
-    mock_agent.run_text.return_value = "Expected output from agent"
-    return mock_agent
-
-
-@pytest.fixture
-def multimodal_agent_tool(multimodal_agent):
-    # Use the mocked MultiModalVisualAgent in the MultiModalVisualAgentTool
-    return MultiModalVisualAgentTool(multimodal_agent)
-
-
-@pytest.mark.parametrize(
-    "text_input, expected_output",
-    [
-        ("Hello, world!", "Expected output from agent"),
-        ("Another task", "Expected output from agent"),
-    ],
-)
-def test_run(multimodal_agent_tool, text_input, expected_output):
-    assert multimodal_agent_tool._run(text_input) == expected_output
-
-    # You can also test if the MultiModalVisualAgent's run_text method was called with the right argument
-    multimodal_agent_tool.agent.run_text.assert_called_with(text_input)
diff --git a/tests/workers/omni_worker.py b/tests/workers/omni_worker.py
deleted file mode 100644
index 0557285d..00000000
--- a/tests/workers/omni_worker.py
+++ /dev/null
@@ -1,58 +0,0 @@
-import pytest
-
-from swarms.worker.omni_worker import OmniWorkerAgent
-
-
-@pytest.fixture
-def omni_worker():
-    api_key = "test-key"
-    api_endpoint = "test-endpoint"
-    api_type = "test-type"
-    return OmniWorkerAgent(api_key, api_endpoint, api_type)
-
-
-@pytest.mark.parametrize(
-    "data, expected_response",
-    [
-        (
-            {
-                "messages": ["Hello"],
-                "api_key": "key1",
-                "api_type": "type1",
-                "api_endpoint": "endpoint1",
-            },
-            {"response": "Hello back from Huggingface!"},
-        ),
-        (
-            {
-                "messages": ["Goodbye"],
-                "api_key": "key2",
-                "api_type": "type2",
-                "api_endpoint": "endpoint2",
-            },
-            {"response": "Goodbye from Huggingface!"},
-        ),
-    ],
-)
-def test_chat_valid_data(mocker, omni_worker, data, expected_response):
-    mocker.patch(
-        "yourmodule.chat_huggingface", return_value=expected_response
-    )  # replace 'yourmodule' with actual module name
-    assert omni_worker.chat(data) == expected_response
-
-
-@pytest.mark.parametrize(
-    "invalid_data",
-    [
-        {"messages": ["Hello"]},  # missing api_key, api_type and api_endpoint
-        {"messages": ["Hello"], "api_key": "key1"},  # missing api_type and api_endpoint
-        {
-            "messages": ["Hello"],
-            "api_key": "key1",
-            "api_type": "type1",
-        },  # missing api_endpoint
-    ],
-)
-def test_chat_invalid_data(omni_worker, invalid_data):
-    with pytest.raises(ValueError):
-        omni_worker.chat(invalid_data)
diff --git a/tests/workers/worker_agent_ultra.py b/tests/workers/worker_agent_ultra.py
deleted file mode 100644
index 3cf112a2..00000000
--- a/tests/workers/worker_agent_ultra.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import pytest
-from unittest.mock import Mock
-from swarms.workers.worker_agent_ultra import WorkerUltraNode  # import your module here
-
-
-def test_create_agent():
-    mock_llm = Mock()
-    mock_toolset = {"test_toolset": Mock()}
-    mock_vectorstore = Mock()
-    worker = WorkerUltraNode(mock_llm, mock_toolset, mock_vectorstore)
-    worker.create_agent()
-    assert worker.agent is not None
-
-
-@pytest.mark.parametrize("invalid_toolset", [123, "string", 0.45])
-def test_add_toolset_invalid(invalid_toolset):
-    mock_llm = Mock()
-    mock_toolset = {"test_toolset": Mock()}
-    mock_vectorstore = Mock()
-    worker = WorkerUltraNode(mock_llm, mock_toolset, mock_vectorstore)
-    with pytest.raises(TypeError):
-        worker.add_toolset(invalid_toolset)
-
-
-@pytest.mark.parametrize("invalid_prompt", [123, None, "", []])
-def test_run_invalid_prompt(invalid_prompt):
-    mock_llm = Mock()
-    mock_toolset = {"test_toolset": Mock()}
-    mock_vectorstore = Mock()
-    worker = WorkerUltraNode(mock_llm, mock_toolset, mock_vectorstore)
-    with pytest.raises((TypeError, ValueError)):
-        worker.run(invalid_prompt)
-
-
-def test_run_valid_prompt(mocker):
-    mock_llm = Mock()
-    mock_toolset = {"test_toolset": Mock()}
-    mock_vectorstore = Mock()
-    worker = WorkerUltraNode(mock_llm, mock_toolset, mock_vectorstore)
-    mocker.patch.object(worker, "create_agent")
-    assert worker.run("Test prompt") == "Task completed by WorkerNode"
-
-
-def test_worker_node():
-    worker = worker_ultra_node("test-key")
-    assert isinstance(worker, WorkerUltraNode)
-
-
-def test_worker_node_no_key():
-    with pytest.raises(ValueError):
-        worker_ultra_node(None)
diff --git a/tests/workers/worker_node.py b/tests/workers/worker_node.py
deleted file mode 100644
index e97b5023..00000000
--- a/tests/workers/worker_node.py
+++ /dev/null
@@ -1,94 +0,0 @@
-import pytest
-from unittest.mock import MagicMock, patch
-from swarms.worker.worker_node import (
-    WorkerNodeInitializer,
-    WorkerNode,
-)  # replace your_module with actual module name
-
-
-# Mock Tool for testing
-class MockTool(Tool):
-    pass
-
-
-# Fixture for llm
-@pytest.fixture
-def mock_llm():
-    return MagicMock()
-
-
-# Fixture for vectorstore
-@pytest.fixture
-def mock_vectorstore():
-    return MagicMock()
-
-
-# Fixture for Tools
-@pytest.fixture
-def mock_tools():
-    return [MockTool(), MockTool(), MockTool()]
-
-
-# Fixture for WorkerNodeInitializer
-@pytest.fixture
-def worker_node(mock_llm, mock_tools, mock_vectorstore):
-    return WorkerNodeInitializer(
-        llm=mock_llm, tools=mock_tools, vectorstore=mock_vectorstore
-    )
-
-
-# Fixture for WorkerNode
-@pytest.fixture
-def mock_worker_node():
-    return WorkerNode(openai_api_key="test_api_key")
-
-
-# WorkerNodeInitializer Tests
-def test_worker_node_init(worker_node):
-    assert worker_node.llm is not None
-    assert worker_node.tools is not None
-    assert worker_node.vectorstore is not None
-
-
-def test_worker_node_create_agent(worker_node):
-    with patch.object(AutoGPT, "from_llm_and_tools") as mock_method:
-        worker_node.create_agent()
-        mock_method.assert_called_once()
-
-
-def test_worker_node_add_tool(worker_node):
-    initial_tools_count = len(worker_node.tools)
-    new_tool = MockTool()
-    worker_node.add_tool(new_tool)
-    assert len(worker_node.tools) == initial_tools_count + 1
-
-
-def test_worker_node_run(worker_node):
-    with patch.object(worker_node.agent, "run") as mock_run:
-        worker_node.run(prompt="test prompt")
-        mock_run.assert_called_once()
-
-
-# WorkerNode Tests
-def test_worker_node_llm(mock_worker_node):
-    with patch.object(mock_worker_node, "initialize_llm") as mock_method:
-        mock_worker_node.initialize_llm(llm_class=MagicMock(), temperature=0.5)
-        mock_method.assert_called_once()
-
-
-def test_worker_node_tools(mock_worker_node):
-    with patch.object(mock_worker_node, "initialize_tools") as mock_method:
-        mock_worker_node.initialize_tools(llm_class=MagicMock())
-        mock_method.assert_called_once()
-
-
-def test_worker_node_vectorstore(mock_worker_node):
-    with patch.object(mock_worker_node, "initialize_vectorstore") as mock_method:
-        mock_worker_node.initialize_vectorstore()
-        mock_method.assert_called_once()
-
-
-def test_worker_node_create_worker_node(mock_worker_node):
-    with patch.object(mock_worker_node, "create_worker_node") as mock_method:
-        mock_worker_node.create_worker_node()
-        mock_method.assert_called_once()
diff --git a/tests/workers/worker_ultra.py b/tests/workers/worker_ultra.py
deleted file mode 100644
index b1485a28..00000000
--- a/tests/workers/worker_ultra.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import pytest
-from unittest.mock import Mock, patch
-from swarms.workers.worker_agent_ultra import (
-    WorkerUltraNode,
-    WorkerUltraNodeInitializer,
-)
-
-
-@pytest.fixture
-def llm_mock():
-    return Mock()
-
-
-@pytest.fixture
-def toolsets_mock():
-    return Mock()
-
-
-@pytest.fixture
-def vectorstore_mock():
-    return Mock()
-
-
-@pytest.fixture
-def worker_ultra_node(llm_mock, toolsets_mock, vectorstore_mock):
-    return WorkerUltraNode(llm_mock, toolsets_mock, vectorstore_mock)
-
-
-def test_worker_ultra_node_create_agent(worker_ultra_node):
-    with patch("yourmodule.AutoGPT.from_llm_and_tools") as mock_method:
-        worker_ultra_node.create_agent()
-        mock_method.assert_called_once()
-
-
-def test_worker_ultra_node_add_toolset(worker_ultra_node):
-    with pytest.raises(TypeError):
-        worker_ultra_node.add_toolset("wrong_toolset")
-
-
-def test_worker_ultra_node_run(worker_ultra_node):
-    with patch.object(worker_ultra_node, "agent") as mock_agent:
-        mock_agent.run.return_value = None
-        result = worker_ultra_node.run("some prompt")
-        assert result == "Task completed by WorkerNode"
-        mock_agent.run.assert_called_once()
-
-
-def test_worker_ultra_node_run_no_prompt(worker_ultra_node):
-    with pytest.raises(ValueError):
-        worker_ultra_node.run("")
-
-
-@pytest.fixture
-def worker_ultra_node_initializer():
-    return WorkerUltraNodeInitializer("openai_api_key")
-
-
-def test_worker_ultra_node_initializer_initialize_llm(worker_ultra_node_initializer):
-    with patch("yourmodule.ChatOpenAI") as mock_llm:
-        worker_ultra_node_initializer.initialize_llm(mock_llm)
-        mock_llm.assert_called_once()
-
-
-def test_worker_ultra_node_initializer_initialize_toolsets(
-    worker_ultra_node_initializer,
-):
-    with patch("yourmodule.Terminal"), patch("yourmodule.CodeEditor"), patch(
-        "yourmodule.RequestsGet"
-    ), patch("yourmodule.ExitConversation"):
-        toolsets = worker_ultra_node_initializer.initialize_toolsets()
-        assert len(toolsets) == 4
-
-
-def test_worker_ultra_node_initializer_initialize_vectorstore(
-    worker_ultra_node_initializer,
-):
-    with patch("yourmodule.OpenAIEmbeddings"), patch(
-        "yourmodule.fauss.IndexFlatL2"
-    ), patch("yourmodule.FAISS"), patch("yourmodule.InMemoryDocstore"):
-        vectorstore = worker_ultra_node_initializer.initialize_vectorstore()
-        assert vectorstore is not None
-
-
-def test_worker_ultra_node_initializer_create_worker_node(
-    worker_ultra_node_initializer,
-):
-    with patch.object(worker_ultra_node_initializer, "initialize_llm"), patch.object(
-        worker_ultra_node_initializer, "initialize_toolsets"
-    ), patch.object(worker_ultra_node_initializer, "initialize_vectorstore"):
-        worker_node = worker_ultra_node_initializer.create_worker_node()
-        assert worker_node is not None