mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-07 17:33:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e717b625d2 | ||
|
|
84638ad759 | ||
|
|
626bc963f7 | ||
|
|
efa7110b38 | ||
|
|
539c10796c | ||
|
|
815becb6f2 | ||
|
|
87790695db | ||
|
|
00b25bb195 | ||
|
|
e46ca3248d | ||
|
|
04f6beaa56 | ||
|
|
3d99326192 | ||
|
|
70ced6acbb | ||
|
|
dc14c06e41 | ||
|
|
deb1148c8a | ||
|
|
3d6d7c0b02 | ||
|
|
1a5a25073e | ||
|
|
7b743e6982 | ||
|
|
77a3512779 | ||
|
|
2a4ec38077 | ||
|
|
25f59b5c26 | ||
|
|
7596ed252d | ||
|
|
14bea558fb | ||
|
|
b5b3d8abd0 | ||
|
|
6f69067450 | ||
|
|
0b06a1c3ed | ||
|
|
8907344649 | ||
|
|
1221bf26e4 | ||
|
|
92263bbb90 | ||
|
|
067769cefb | ||
|
|
947d301cb5 | ||
|
|
3c96d50fbd | ||
|
|
b744c4fbf5 | ||
|
|
2b79201f0f | ||
|
|
5bf86cd8bf | ||
|
|
0f2bb67e5f | ||
|
|
b58b7d6680 | ||
|
|
756f5ecebd | ||
|
|
4341fdda1c | ||
|
|
6261f574c3 | ||
|
|
8740a16f4a | ||
|
|
c183c211dc | ||
|
|
e42a8ec652 | ||
|
|
fd3511200d | ||
|
|
cdb1da765c | ||
|
|
b5fb9051ac | ||
|
|
8414c9d0d8 | ||
|
|
ef82448569 | ||
|
|
e5830de8ad | ||
|
|
fb4035437c | ||
|
|
2e3a37ed52 | ||
|
|
87513c2c44 | ||
|
|
542701f989 | ||
|
|
b5b1aa7dd7 | ||
|
|
2e0480543f | ||
|
|
b4991caa18 | ||
|
|
17436324db | ||
|
|
9c26d6d1dc | ||
|
|
f1842c3d08 | ||
|
|
6bac8cbafe | ||
|
|
6e0223a473 | ||
|
|
3e21d31899 | ||
|
|
1323f9711c | ||
|
|
51f01fa6c6 | ||
|
|
7df52d32cf | ||
|
|
6ddea1d5b6 | ||
|
|
ecb21e32ec | ||
|
|
4e23d5ca41 | ||
|
|
4c29c14c2e | ||
|
|
2a1549c8cd | ||
|
|
09c6c321e8 | ||
|
|
63700a0bbc | ||
|
|
a28bf4b063 | ||
|
|
ef87c1b643 |
No files matched your search
@@ -0,0 +1,524 @@
|
||||
name: Release Workflow
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to create release with (e.g., v2.0.10)'
|
||||
required: true
|
||||
fork_owner:
|
||||
description: 'GitHub username of the fork owner'
|
||||
required: true
|
||||
default: 'tosin2013'
|
||||
|
||||
jobs:
|
||||
test-ubuntu:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-24.04]
|
||||
framework: ['crewai', 'autogen']
|
||||
fail-fast: false
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 90
|
||||
|
||||
steps:
|
||||
# First checkout the upstream repo at the specified tag
|
||||
- name: Checkout upstream repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: MervinPraison/PraisonAI
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
fetch-depth: 0
|
||||
|
||||
# Get the commit hash from the tag
|
||||
- name: Get commit hash
|
||||
id: get_commit
|
||||
run: |
|
||||
COMMIT_HASH=$(git rev-parse HEAD)
|
||||
echo "commit_hash=$COMMIT_HASH" >> $GITHUB_OUTPUT
|
||||
echo "Found commit: $COMMIT_HASH for tag ${{ github.event.inputs.tag }}"
|
||||
|
||||
# Now checkout the fork at main branch
|
||||
- name: Checkout fork
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.event.inputs.fork_owner }}/PraisonAI
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
clean: true
|
||||
|
||||
# Sync with upstream commit
|
||||
- name: Sync with upstream
|
||||
run: |
|
||||
git config --global user.name "GitHub Actions"
|
||||
git config --global user.email "[email protected]"
|
||||
|
||||
# Add upstream remote
|
||||
git remote add upstream https://github.com/MervinPraison/PraisonAI.git
|
||||
|
||||
# Fetch from upstream
|
||||
git fetch upstream --tags --force
|
||||
|
||||
# Reset to upstream commit
|
||||
git reset --hard ${{ steps.get_commit.outputs.commit_hash }}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install Poetry
|
||||
run: |
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
poetry config virtualenvs.in-project true
|
||||
poetry config virtualenvs.create true
|
||||
poetry --version
|
||||
poetry config --list
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
poetry lock #--no-update
|
||||
poetry install --all-extras
|
||||
poetry env info
|
||||
# Verify venv exists
|
||||
test -d .venv || { echo "Virtual environment not created!"; exit 1; }
|
||||
test -f .venv/bin/activate || { echo "Activation script not found!"; exit 1; }
|
||||
|
||||
- name: Run setup script
|
||||
timeout-minutes: 20
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
curl -OL https://raw.githubusercontent.com/tosin2013/PraisonAI/refs/heads/main/setup.sh
|
||||
chmod +x setup.sh
|
||||
./setup.sh --all --cicd || { echo "Setup script failed"; exit 1; }
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Test Basic Functionality
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
|
||||
# Random sleep between 60-120 seconds to avoid API rate limits
|
||||
SLEEP_TIME=$((RANDOM % 61 + 60))
|
||||
echo "Sleeping for $SLEEP_TIME seconds to avoid API rate limits..."
|
||||
sleep $SLEEP_TIME
|
||||
|
||||
lsof -ti:8084 | xargs -r kill -9 || true
|
||||
source .venv/bin/activate || { echo "Failed to activate virtual environment"; exit 1; }
|
||||
mkdir -p test_output || { echo "Failed to create test_output directory"; exit 1; }
|
||||
|
||||
echo "Testing basic CLI functionality..."
|
||||
|
||||
# Test auto generation with explicit framework
|
||||
praisonai --framework ${{ matrix.framework }} --auto "create a short test script" 2>&1 | tee test_output/auto_test.log
|
||||
|
||||
# Verify the output file exists and has content
|
||||
if [[ ! -s test_output/auto_test.log ]]; then
|
||||
echo "Error: No output generated from auto test"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test auto generation without framework
|
||||
echo "Basic functionality tests passed!"
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
LOGLEVEL: "debug"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Test Framework-specific Features
|
||||
continue-on-error: false
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
|
||||
# Random sleep between 60-120 seconds to avoid API rate limits
|
||||
SLEEP_TIME=$((RANDOM % 61 + 60))
|
||||
echo "Sleeping for $SLEEP_TIME seconds to avoid API rate limits..."
|
||||
sleep $SLEEP_TIME
|
||||
|
||||
lsof -ti:8084 | xargs -r kill -9 || true
|
||||
praisonai --framework ${{ matrix.framework }} --auto "create a movie script about Robots in Mars" 2>&1 | tee test_output/framework_output.txt || echo "Framework-specific test failed" >> test_output/errors.log
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Test Core Functionality
|
||||
continue-on-error: false
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
|
||||
# Random sleep between 60-120 seconds to avoid API rate limits
|
||||
SLEEP_TIME=$((RANDOM % 61 + 60))
|
||||
echo "Sleeping for $SLEEP_TIME seconds to avoid API rate limits..."
|
||||
sleep $SLEEP_TIME
|
||||
|
||||
echo "Testing core functionality..."
|
||||
|
||||
# Test package imports
|
||||
python3 -c "from praisonai.cli import PraisonAI; from praisonai.auto import AutoGenerator; from praisonai.agents_generator import AgentsGenerator" || exit 1
|
||||
|
||||
# Test configuration loading
|
||||
python3 -c "from praisonai.inc.config import generate_config; print(generate_config())" || exit 1
|
||||
|
||||
# Test tools loading
|
||||
python3 -c "from praisonai.inbuilt_tools import *" || exit 1
|
||||
|
||||
echo "Core functionality tests passed!"
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
LOGLEVEL: "debug"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Test Agent Generation
|
||||
continue-on-error: false
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
|
||||
# Random sleep between 60-120 seconds to avoid API rate limits
|
||||
SLEEP_TIME=$((RANDOM % 61 + 60))
|
||||
echo "Sleeping for $SLEEP_TIME seconds to avoid API rate limits..."
|
||||
sleep $SLEEP_TIME
|
||||
|
||||
echo "Testing agent generation..."
|
||||
|
||||
# Create a test YAML file
|
||||
cat > test_agents.yaml <<EOF
|
||||
topic: "Test automation task"
|
||||
framework: "${{ matrix.framework }} "
|
||||
roles:
|
||||
- name: "Tester"
|
||||
goal: "Test the system"
|
||||
backstory: "Expert system tester"
|
||||
tasks:
|
||||
- description: "Verify system functionality"
|
||||
expected_output: "Test results"
|
||||
EOF
|
||||
|
||||
# Test YAML loading and agent generation
|
||||
python3 -c '
|
||||
from praisonai.agents_generator import AgentsGenerator
|
||||
config = [{"model": "llama-3.3-70b-versatile", "base_url": "https://api.groq.com/openai/v1/"}]
|
||||
generator = AgentsGenerator("test_agents.yaml", "${{ matrix.framework }} ", config)
|
||||
print("Agent generation test passed!")
|
||||
' || exit 1
|
||||
|
||||
echo "Agent generation tests passed!"
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
LOGLEVEL: "debug"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Test Custom Tools Integration
|
||||
continue-on-error: false
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
|
||||
# Random sleep between 60-120 seconds to avoid API rate limits
|
||||
SLEEP_TIME=$((RANDOM % 61 + 60))
|
||||
echo "Sleeping for $SLEEP_TIME seconds to avoid API rate limits..."
|
||||
sleep $SLEEP_TIME
|
||||
|
||||
echo "Testing custom tools integration..."
|
||||
|
||||
# Create a test tool
|
||||
cat > test_tool.py <<EOF
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "Internet Search Tool"
|
||||
description: str = "Search Internet for relevant information"
|
||||
|
||||
def _run(self, query: str):
|
||||
return {"status": "success", "query": query}
|
||||
|
||||
def test(self):
|
||||
"""Test method to verify tool setup"""
|
||||
test_query = "test query"
|
||||
result = self._run(test_query)
|
||||
assert result["status"] == "success"
|
||||
assert result["query"] == test_query
|
||||
return True
|
||||
EOF
|
||||
|
||||
# Test tool loading and initialization
|
||||
python3 -c '
|
||||
import importlib.util
|
||||
import sys
|
||||
|
||||
# Load the test tool
|
||||
spec = importlib.util.spec_from_file_location("test_tool", "test_tool.py")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules["test_tool"] = module
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
# Initialize and test the tool
|
||||
tool = module.InternetSearchTool()
|
||||
assert tool.test(), "Tool test failed"
|
||||
print("Custom tool test passed!")
|
||||
' || exit 1
|
||||
|
||||
echo "Custom tools integration test passed!"
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
LOGLEVEL: "debug"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Test PraisonAI Agents Configuration
|
||||
continue-on-error: false
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
|
||||
# Random sleep between 60-120 seconds to avoid API rate limits
|
||||
SLEEP_TIME=$((RANDOM % 61 + 60))
|
||||
echo "Sleeping for $SLEEP_TIME seconds to avoid API rate limits..."
|
||||
sleep $SLEEP_TIME
|
||||
|
||||
echo "Testing agents configuration..."
|
||||
mkdir -p test_output || { echo "Failed to create test_output directory"; exit 1; }
|
||||
|
||||
# Create test script
|
||||
cat > test_agents.py <<EOF
|
||||
from langchain_openai import ChatOpenAI
|
||||
from crewai import Agent, Task, Crew
|
||||
import os
|
||||
import logging
|
||||
import time
|
||||
import random
|
||||
|
||||
logging.basicConfig(level="DEBUG")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def random_sleep(min_seconds=15, max_seconds=30):
|
||||
"""Sleep for a random duration to prevent API rate limiting"""
|
||||
duration = random.uniform(min_seconds, max_seconds)
|
||||
logger.info(f"Rate limit protection: Sleeping for {duration:.2f} seconds...")
|
||||
time.sleep(duration)
|
||||
|
||||
class RateLimitedChatOpenAI(ChatOpenAI):
|
||||
"""ChatOpenAI with built-in rate limiting"""
|
||||
def __call__(self, *args, **kwargs):
|
||||
random_sleep()
|
||||
return super().__call__(*args, **kwargs)
|
||||
|
||||
def run_test():
|
||||
logger.info("Initializing test components...")
|
||||
|
||||
# Initialize the LLM with rate limiting
|
||||
llm = RateLimitedChatOpenAI(
|
||||
model=os.getenv('OPENAI_MODEL_NAME', 'llama-3.3-70b-versatile'),
|
||||
base_url=os.getenv('OPENAI_API_BASE', 'https://api.groq.com/openai/v1/'),
|
||||
api_key=os.getenv('OPENAI_API_KEY'),
|
||||
temperature=0.7
|
||||
)
|
||||
|
||||
random_sleep()
|
||||
logger.info("Creating researcher agent...")
|
||||
researcher = Agent(
|
||||
role="Test Automation Expert",
|
||||
goal="Verify system functionality and performance",
|
||||
backstory="""You are an expert in test automation and system verification,
|
||||
skilled in identifying potential issues and validating functionality.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
llm=llm
|
||||
)
|
||||
|
||||
random_sleep()
|
||||
logger.info("Creating validator agent...")
|
||||
validator = Agent(
|
||||
role="Quality Assurance Specialist",
|
||||
goal="Validate test results and ensure system reliability",
|
||||
backstory="""You are a QA specialist focused on ensuring
|
||||
system reliability and proper functionality.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
llm=llm
|
||||
)
|
||||
|
||||
random_sleep()
|
||||
logger.info("Creating test tasks...")
|
||||
test_task = Task(
|
||||
description="Run a basic system verification test",
|
||||
expected_output="A report on system functionality verification",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
random_sleep()
|
||||
validation_task = Task(
|
||||
description="Validate the test results and compile findings",
|
||||
expected_output="A validation report of test findings",
|
||||
agent=validator
|
||||
)
|
||||
|
||||
random_sleep()
|
||||
logger.info("Initializing crew...")
|
||||
crew = Crew(
|
||||
agents=[researcher, validator],
|
||||
tasks=[test_task, validation_task],
|
||||
verbose=2
|
||||
)
|
||||
|
||||
logger.info("Starting crew execution...")
|
||||
result = crew.kickoff()
|
||||
logger.info("Test execution completed.")
|
||||
logger.info(f"Result: {result}")
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
run_test()
|
||||
except Exception as e:
|
||||
logger.error(f"Test failed with error: {str(e)}", exc_info=True)
|
||||
raise
|
||||
EOF
|
||||
|
||||
# Run the test script with increased timeout
|
||||
echo "Testing with Python API..."
|
||||
timeout 1800 python3 test_agents.py 2>&1 | tee test_output/agents_test.log
|
||||
|
||||
# Verify the output
|
||||
if [[ ! -s test_output/agents_test.log ]]; then
|
||||
echo "Error: No output generated from agents test"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Agents configuration tests passed!"
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
OPENAI_MODEL_NAME: "llama-3.3-70b-versatile"
|
||||
OPENAI_API_BASE: "https://api.groq.com/openai/v1/"
|
||||
OPENAI_API_BASE_URL: "https://api.groq.com/openai/v1/"
|
||||
LOGLEVEL: "debug"
|
||||
PRAISONAI_NON_INTERACTIVE: "true"
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: praisonai-output-${{ matrix.os }}-${{ matrix.framework }}
|
||||
path: test_output/
|
||||
retention-days: 14
|
||||
|
||||
create-release:
|
||||
needs: [test-ubuntu]
|
||||
runs-on: ubuntu-latest
|
||||
if: success()
|
||||
steps:
|
||||
# First checkout the fork's main branch
|
||||
- name: Checkout fork repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.PAT_TOKEN }}
|
||||
repository: ${{ github.event.inputs.fork_owner }}/PraisonAI
|
||||
ref: main
|
||||
|
||||
# Add upstream and get commit from tag
|
||||
- name: Get upstream tag commit
|
||||
id: get_upstream_commit
|
||||
run: |
|
||||
# Add upstream remote
|
||||
git remote add upstream https://github.com/MervinPraison/PraisonAI.git
|
||||
|
||||
# Delete local tag if it exists
|
||||
git tag -d ${{ github.event.inputs.tag }} || true
|
||||
|
||||
# Fetch from upstream including tags with force
|
||||
git fetch upstream --tags --force
|
||||
|
||||
# Verify tag exists in upstream
|
||||
if ! git ls-remote --tags upstream | grep -q "refs/tags/${{ github.event.inputs.tag }}$"; then
|
||||
echo "::error::Tag ${{ github.event.inputs.tag }} not found in upstream repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the commit hash from the upstream tag
|
||||
UPSTREAM_COMMIT=$(git rev-list -n 1 refs/tags/${{ github.event.inputs.tag }})
|
||||
if [ -z "$UPSTREAM_COMMIT" ]; then
|
||||
echo "::error::Could not find commit for tag ${{ github.event.inputs.tag }}"
|
||||
exit 1
|
||||
fi
|
||||
echo "upstream_commit=$UPSTREAM_COMMIT" >> $GITHUB_OUTPUT
|
||||
echo "Found commit: $UPSTREAM_COMMIT for tag ${{ github.event.inputs.tag }}"
|
||||
|
||||
# Create tag at the same commit
|
||||
- name: Create tag at commit
|
||||
run: |
|
||||
git config --global user.name "GitHub Actions"
|
||||
git config --global user.email "[email protected]"
|
||||
|
||||
# Remove tag if it exists locally
|
||||
git tag -d ${{ github.event.inputs.tag }} || true
|
||||
|
||||
# Remove tag if it exists remotely
|
||||
git push origin :refs/tags/${{ github.event.inputs.tag }} || true
|
||||
|
||||
# Fetch the specific commit from upstream
|
||||
git fetch upstream ${{ steps.get_upstream_commit.outputs.upstream_commit }} --force
|
||||
|
||||
# Reset to upstream commit
|
||||
git reset --hard ${{ steps.get_upstream_commit.outputs.upstream_commit }}
|
||||
|
||||
# Create and push tag
|
||||
git tag -a ${{ github.event.inputs.tag }} -m "Release ${{ github.event.inputs.tag }} (synced from upstream MervinPraison/PraisonAI@${{ github.event.inputs.tag }})"
|
||||
git push origin ${{ github.event.inputs.tag }}
|
||||
env:
|
||||
GIT_ASKPASS: /bin/echo
|
||||
PAT_TOKEN: ${{ secrets.PAT_TOKEN }}
|
||||
|
||||
# Create the release
|
||||
- name: Create Release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.event.inputs.tag }}
|
||||
release_name: Release ${{ github.event.inputs.tag }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: |
|
||||
Release ${{ github.event.inputs.tag }} (synced from upstream)
|
||||
|
||||
This release is synchronized with MervinPraison/PraisonAI@${{ github.event.inputs.tag }}
|
||||
Commit: ${{ steps.get_upstream_commit.outputs.upstream_commit }}
|
||||
|
||||
For installation:
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
|
||||
Changes from upstream v2.0.10:
|
||||
- Updated agent configuration tests
|
||||
- Added rate limiting protection
|
||||
- Improved test reliability
|
||||
|
||||
Forked from: MervinPraison/PraisonAI
|
||||
+2
-1
@@ -64,4 +64,5 @@ node_modules
|
||||
outputs
|
||||
agents/praisonaiagents/build
|
||||
agents/praisonaiagents/dist
|
||||
agents/praisonaiagents/praisonaiagents.egg-info
|
||||
agents/praisonaiagents/praisonaiagents.egg-info
|
||||
.codegpt
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install flask praisonai==2.0.14 gunicorn markdown
|
||||
RUN pip install flask praisonai==2.0.26 gunicorn markdown
|
||||
EXPOSE 8080
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
|
||||
@@ -0,0 +1,24 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
python3-dev \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Python packages
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonaiagents>=0.0.4 \
|
||||
praisonai_tools \
|
||||
"praisonai==2.0.18" \
|
||||
"praisonai[chat]" \
|
||||
"embedchain[github,youtube]"
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Default command (will be overridden by docker-compose)
|
||||
CMD ["praisonai", "chat"]
|
||||
@@ -0,0 +1,28 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
python3-dev \
|
||||
portaudio19-dev \
|
||||
python3-pyaudio \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Python packages
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonaiagents>=0.0.4 \
|
||||
praisonai_tools \
|
||||
"praisonai==2.0.18" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[chat]" \
|
||||
"praisonai[realtime]" \
|
||||
"embedchain[github,youtube]"
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Default command (will be overridden by docker-compose)
|
||||
CMD ["praisonai", "ui"]
|
||||
@@ -0,0 +1,24 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
python3-dev \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Python packages
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonaiagents>=0.0.4 \
|
||||
praisonai_tools \
|
||||
"praisonai==2.0.18" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Default command (will be overridden by docker-compose)
|
||||
CMD ["praisonai", "ui"]
|
||||
@@ -22,17 +22,30 @@
|
||||
|
||||
PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration.
|
||||
|
||||
<div align="center">
|
||||
<a href="https://docs.praison.ai">
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/📚_Documentation-Visit_docs.praison.ai-blue?style=for-the-badge&logo=bookstack&logoColor=white" alt="Documentation" />
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Key Features
|
||||
|
||||
- 🤖 Automated AI Agents Creation
|
||||
- 🔄 Self Reflection AI Agents
|
||||
- 🧠 Reasoning AI Agents
|
||||
- 👁️ Multi Modal AI Agents
|
||||
- 🤝 Multi Agent Collaboration
|
||||
- ⚡ AI Agent Workflow
|
||||
- 🔄 Use CrewAI or AutoGen Framework
|
||||
- 💯 100+ LLM Support
|
||||
- 💻 Chat with ENTIRE Codebase
|
||||
- 🖥️ Interactive UIs
|
||||
- 🎨 Interactive UIs
|
||||
- 📄 YAML-based Configuration
|
||||
- 🛠️ Custom Tool Integration
|
||||
- 🔍 Internet Search Capability (using Crawl4AI and Tavily)
|
||||
- 👁️ Vision Language Model (VLM) Support
|
||||
- 🖼️ Vision Language Model (VLM) Support
|
||||
- 🎙️ Real-time Voice Interaction
|
||||
|
||||
## Using No Code
|
||||
@@ -464,33 +477,7 @@ if __name__ == "__main__":
|
||||
|
||||
## Commands to Install Dependencies:
|
||||
|
||||
1. **Install all dependencies, including dev dependencies:**
|
||||
|
||||
```sh
|
||||
poetry install
|
||||
```
|
||||
|
||||
2. **Install only documentation dependencies:**
|
||||
|
||||
```sh
|
||||
poetry install --with docs
|
||||
```
|
||||
|
||||
3. **Install only test dependencies:**
|
||||
|
||||
```sh
|
||||
poetry install --with test
|
||||
```
|
||||
|
||||
4. **Install only dev dependencies:**
|
||||
|
||||
```sh
|
||||
poetry install --with dev
|
||||
```
|
||||
|
||||
This configuration ensures that your development dependencies are correctly categorized and installed as needed.
|
||||
|
||||
### Using uv (Fast Python Package Installer)
|
||||
### Using uv
|
||||
```bash
|
||||
# Install uv if you haven't already
|
||||
pip install uv
|
||||
@@ -541,3 +528,55 @@ Praison AI is an open-sourced software licensed under the **[MIT license](https:
|
||||
## License
|
||||
|
||||
Praison AI is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
|
||||
|
||||
## Local Docker Development with Live Reload
|
||||
|
||||
To facilitate local development with live reload, you can use Docker. Follow the steps below:
|
||||
|
||||
1. **Create a `Dockerfile.dev`**:
|
||||
```dockerfile
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN pip install flask praisonai==2.0.18 watchdog
|
||||
|
||||
EXPOSE 5555
|
||||
|
||||
ENV FLASK_ENV=development
|
||||
|
||||
CMD ["flask", "run", "--host=0.0.0.0"]
|
||||
```
|
||||
|
||||
2. **Create a `docker-compose.yml`**:
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
volumes:
|
||||
- .:/app
|
||||
ports:
|
||||
- "5555:5555"
|
||||
environment:
|
||||
FLASK_ENV: development
|
||||
command: flask run --host=0.0.0.0
|
||||
|
||||
watch:
|
||||
image: alpine:latest
|
||||
volumes:
|
||||
- .:/app
|
||||
command: sh -c "apk add --no-cache inotify-tools && while inotifywait -r -e modify,create,delete /app; do kill -HUP 1; done"
|
||||
```
|
||||
|
||||
3. **Run Docker Compose**:
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
This setup will allow you to develop locally with live reload, making it easier to test and iterate on your code.
|
||||
+4
-8
@@ -7,22 +7,20 @@ roles:
|
||||
information.
|
||||
goal: Gather information about Mars and cats
|
||||
role: Researcher
|
||||
llm:
|
||||
model: "gpt-4o"
|
||||
min_reflect: 1
|
||||
max_reflect: 2
|
||||
tasks:
|
||||
research_task:
|
||||
description: Research about Mars, its environment, and the feasibility of
|
||||
a cat being on Mars. Also, research about cat behavior and characteristics.
|
||||
expected_output: Document with research findings on Mars and cats.
|
||||
tools:
|
||||
- 'search_tool'
|
||||
- search_tool
|
||||
narrative_designer:
|
||||
backstory: Skilled in narrative development, with a focus on creating engaging
|
||||
stories.
|
||||
goal: Create a story concept for a movie about a cat in Mars
|
||||
role: Narrative Designer
|
||||
llm:
|
||||
model: "gpt-4o"
|
||||
tasks:
|
||||
story_concept_development:
|
||||
description: Use the research findings to craft a unique story concept for
|
||||
@@ -35,8 +33,6 @@ roles:
|
||||
scripts.
|
||||
goal: Write a movie script about a cat in Mars
|
||||
role: Scriptwriter
|
||||
llm:
|
||||
model: "gpt-4o"
|
||||
tasks:
|
||||
scriptwriting_task:
|
||||
description: Turn the story concept into a production-ready movie script,
|
||||
@@ -44,4 +40,4 @@ roles:
|
||||
expected_output: Final movie script with dialogue and scene details.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
dependencies: []
|
||||
@@ -81,3 +81,6 @@ praisonaiagents/dist
|
||||
praisonaiagents/praisonaiagents.egg-info
|
||||
dist
|
||||
build
|
||||
*.mp4
|
||||
*.png
|
||||
graph.py
|
||||
@@ -0,0 +1,233 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from praisonaiagents.main import (
|
||||
display_error,
|
||||
display_interaction,
|
||||
display_tool_call,
|
||||
display_instruction,
|
||||
error_logs,
|
||||
Console
|
||||
)
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
console = Console()
|
||||
|
||||
# 1. Define output model for structured results
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
# 2. Define both sync and async tools
|
||||
def sync_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Synchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
list: Search results
|
||||
"""
|
||||
display_tool_call(f"Running sync search for: {query}", console)
|
||||
time.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error during sync search: {e}"
|
||||
display_error(error_msg, console)
|
||||
error_logs.append(error_msg)
|
||||
return []
|
||||
|
||||
async def async_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Asynchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
list: Search results
|
||||
"""
|
||||
display_tool_call(f"Running async search for: {query}", console)
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error during async search: {e}"
|
||||
display_error(error_msg, console)
|
||||
error_logs.append(error_msg)
|
||||
return []
|
||||
|
||||
# 3. Define both sync and async callbacks
|
||||
def sync_callback(output: TaskOutput):
|
||||
display_interaction("Sync Callback", f"Processing output: {output.raw[:100]}...", markdown=True, console=console)
|
||||
time.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
display_tool_call(f"Processed JSON result: {output.json_dict}", console)
|
||||
elif output.output_format == "Pydantic":
|
||||
display_tool_call(f"Processed Pydantic result: {output.pydantic}", console)
|
||||
|
||||
async def async_callback(output: TaskOutput):
|
||||
display_interaction("Async Callback", f"Processing output: {output.raw[:100]}...", markdown=True, console=console)
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
display_tool_call(f"Processed JSON result: {output.json_dict}", console)
|
||||
elif output.output_format == "Pydantic":
|
||||
display_tool_call(f"Processed Pydantic result: {output.pydantic}", console)
|
||||
|
||||
# 4. Create agents with different tools
|
||||
sync_agent = Agent(
|
||||
name="SyncAgent",
|
||||
role="Synchronous Search Specialist",
|
||||
goal="Perform synchronous searches and return structured results",
|
||||
backstory="Expert in sync operations and data organization",
|
||||
tools=[sync_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
async_agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Asynchronous Search Specialist",
|
||||
goal="Perform asynchronous searches and return structured results",
|
||||
backstory="Expert in async operations and data organization",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 5. Create tasks with different configurations
|
||||
sync_task = Task(
|
||||
name="sync_search",
|
||||
description="Search for 'Python programming' using sync tool and return structured results",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=sync_agent,
|
||||
async_execution=False,
|
||||
callback=sync_callback,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="Search for 'Async programming' using async tool and return structured results",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
# 6. Create workflow tasks
|
||||
workflow_sync_task = Task(
|
||||
name="workflow_sync",
|
||||
description="Workflow sync search for 'AI trends' with structured output",
|
||||
expected_output="SearchResult model with AI trends data",
|
||||
agent=sync_agent,
|
||||
async_execution=False,
|
||||
is_start=True,
|
||||
next_tasks=["workflow_async"],
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
workflow_async_task = Task(
|
||||
name="workflow_async",
|
||||
description="Workflow async search for 'Future of AI' with structured output",
|
||||
expected_output="SearchResult model with Future of AI data",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
# 7. Example usage functions
|
||||
def run_sync_example():
|
||||
"""Run synchronous example"""
|
||||
display_instruction("\nRunning Synchronous Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent],
|
||||
tasks=[sync_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = agents.start()
|
||||
display_interaction("Sync Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
async def run_async_example():
|
||||
"""Run asynchronous example"""
|
||||
display_instruction("\nRunning Asynchronous Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
display_interaction("Async Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
async def run_mixed_example():
|
||||
"""Run mixed sync/async example"""
|
||||
display_instruction("\nRunning Mixed Sync/Async Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent, async_agent],
|
||||
tasks=[sync_task, async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
display_interaction("Mixed Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
async def run_workflow_example():
|
||||
"""Run workflow example with both sync and async tasks"""
|
||||
display_instruction("\nRunning Workflow Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent, async_agent],
|
||||
tasks=[workflow_sync_task, workflow_async_task],
|
||||
verbose=1,
|
||||
process="workflow"
|
||||
)
|
||||
result = await agents.astart()
|
||||
display_interaction("Workflow Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
# 8. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
display_instruction("Starting PraisonAI Agents Examples...", console)
|
||||
|
||||
try:
|
||||
# Run sync example in a separate thread to not block the event loop
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, run_sync_example)
|
||||
|
||||
# Run async examples
|
||||
await run_async_example()
|
||||
await run_mixed_example()
|
||||
await run_workflow_example()
|
||||
|
||||
if error_logs:
|
||||
display_error("\nErrors encountered during execution:", console)
|
||||
for error in error_logs:
|
||||
display_error(error, console)
|
||||
except Exception as e:
|
||||
display_error(f"Error in main execution: {e}", console)
|
||||
error_logs.append(str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,152 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
# 1. Define output model for structured results
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
# 2. Define async tool
|
||||
async def async_search_tool(query: str) -> Dict:
|
||||
"""Perform asynchronous search and return structured results."""
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
|
||||
return {
|
||||
"query": query,
|
||||
"results": results,
|
||||
"total_results": len(results)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error during async search: {e}")
|
||||
return {
|
||||
"query": query,
|
||||
"results": [],
|
||||
"total_results": 0
|
||||
}
|
||||
|
||||
# 3. Define async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
print(f"Processed JSON result: {output.json_dict}")
|
||||
elif output.output_format == "Pydantic":
|
||||
print(f"Processed Pydantic result: {output.pydantic}")
|
||||
|
||||
# 4. Create specialized agents
|
||||
async_agent = Agent(
|
||||
name="AsyncSearchAgent",
|
||||
role="Search Specialist",
|
||||
goal="Perform fast parallel searches with structured results",
|
||||
backstory="Expert in efficient data retrieval and parallel search operations",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
summary_agent = Agent(
|
||||
name="SummaryAgent",
|
||||
role="Research Synthesizer",
|
||||
goal="Create concise summaries from multiple search results",
|
||||
backstory="Expert in analyzing and synthesizing information from multiple sources",
|
||||
self_reflect=True,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 5. Create async tasks
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="Search for 'Async programming' and return results in JSON format with query, results array, and total_results count.",
|
||||
expected_output="SearchResult model with structured data",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
)
|
||||
|
||||
async def run_parallel_tasks():
|
||||
"""Run multiple async tasks in parallel"""
|
||||
print("\nRunning Parallel Async Tasks...")
|
||||
|
||||
# Define different search topics
|
||||
search_topics = [
|
||||
"Latest AI Developments 2024",
|
||||
"Machine Learning Best Practices",
|
||||
"Neural Networks Architecture"
|
||||
]
|
||||
|
||||
# Create tasks for different topics
|
||||
parallel_tasks = [
|
||||
Task(
|
||||
name=f"search_task_{i}",
|
||||
description=f"Search for '{topic}' and return structured results with query details and findings.",
|
||||
expected_output="SearchResult model with search data",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
) for i, topic in enumerate(search_topics)
|
||||
]
|
||||
|
||||
# Create summarization task
|
||||
summary_task = Task(
|
||||
name="summary_task",
|
||||
description="Analyze all search results and create a concise summary highlighting key findings, patterns, and implications.",
|
||||
expected_output="Structured summary with key findings and insights",
|
||||
agent=summary_agent,
|
||||
async_execution=False,
|
||||
callback=async_callback,
|
||||
context=parallel_tasks
|
||||
)
|
||||
|
||||
# Create a single PraisonAIAgents instance with both agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent, summary_agent],
|
||||
tasks=parallel_tasks + [summary_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Run all tasks
|
||||
results = await agents.astart()
|
||||
print(f"Tasks Results: {results}")
|
||||
|
||||
# Return results in a serializable format
|
||||
return {
|
||||
"search_results": {
|
||||
"task_status": {k: v for k, v in results["task_status"].items() if k != summary_task.id},
|
||||
"task_results": [str(results["task_results"][i]) if results["task_results"][i] else None
|
||||
for i in range(len(parallel_tasks))]
|
||||
},
|
||||
"summary": str(results["task_results"][summary_task.id]) if results["task_results"].get(summary_task.id) else None,
|
||||
"topics": search_topics
|
||||
}
|
||||
|
||||
# 6. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
print("Starting Async AI Agents Examples...")
|
||||
|
||||
try:
|
||||
await run_parallel_tasks()
|
||||
except Exception as e:
|
||||
print(f"Error in main execution: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,248 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
# 1. Define output model for structured results
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
# 2. Define async tool
|
||||
async def async_search_tool(query: str) -> Dict:
|
||||
"""
|
||||
Asynchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
dict: Search results in SearchResult model format
|
||||
"""
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
|
||||
# Format response to match SearchResult model
|
||||
return {
|
||||
"query": query,
|
||||
"results": results,
|
||||
"total_results": len(results)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error during async search: {e}")
|
||||
return {
|
||||
"query": query,
|
||||
"results": [],
|
||||
"total_results": 0
|
||||
}
|
||||
|
||||
# 3. Define async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
print(f"Processed JSON result: {output.json_dict}")
|
||||
elif output.output_format == "Pydantic":
|
||||
print(f"Processed Pydantic result: {output.pydantic}")
|
||||
|
||||
# 4. Create specialized agents
|
||||
async_agent = Agent(
|
||||
name="AsyncSearchAgent",
|
||||
role="Asynchronous Search Specialist",
|
||||
goal="Perform fast and efficient asynchronous searches with structured results",
|
||||
backstory="Expert in parallel search operations and data retrieval",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
summary_agent = Agent(
|
||||
name="SummaryAgent",
|
||||
role="Research Synthesizer",
|
||||
goal="Create comprehensive summaries and identify patterns across multiple search results",
|
||||
backstory="""Expert in analyzing and synthesizing information from multiple sources.
|
||||
Skilled at identifying patterns, trends, and connections between different topics.
|
||||
Specializes in creating clear, structured summaries that highlight key insights.""",
|
||||
self_reflect=True, # Enable self-reflection for better summary quality
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 5. Create async tasks
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="""Search for 'Async programming' and return results in the following JSON format:
|
||||
{
|
||||
"query": "the search query",
|
||||
"results": [
|
||||
{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}
|
||||
],
|
||||
"total_results": number of results
|
||||
}""",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
)
|
||||
|
||||
# 6. Example usage functions
|
||||
async def run_single_task():
|
||||
"""Run single async task"""
|
||||
print("\nRunning Single Async Task...")
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
print(f"Single Task Result: {result}")
|
||||
|
||||
async def run_parallel_tasks():
|
||||
"""Run multiple async tasks in parallel"""
|
||||
print("\nRunning Parallel Async Tasks...")
|
||||
|
||||
# Define different search topics
|
||||
search_topics = [
|
||||
"Latest AI Developments 2024",
|
||||
"Machine Learning Best Practices",
|
||||
"Neural Networks Architecture"
|
||||
]
|
||||
|
||||
# Create tasks for different topics
|
||||
parallel_tasks = [
|
||||
Task(
|
||||
name=f"search_task_{i}",
|
||||
description=f"""Search for '{topic}' and return results in the following JSON format:
|
||||
{{
|
||||
"query": "{topic}",
|
||||
"results": [
|
||||
{{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}}
|
||||
],
|
||||
"total_results": number of results
|
||||
}}""",
|
||||
expected_output="SearchResult model with detailed information",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
) for i, topic in enumerate(search_topics)
|
||||
]
|
||||
|
||||
# Create summarization task with the specialized summary agent
|
||||
summary_task = Task(
|
||||
name="summary_task",
|
||||
description="""As a Research Synthesizer, analyze the search results and create a comprehensive summary. Your task:
|
||||
|
||||
1. Analyze Results:
|
||||
- Review all search results thoroughly
|
||||
- Extract key findings from each topic
|
||||
- Identify main themes and concepts
|
||||
|
||||
2. Find Connections:
|
||||
- Identify relationships between topics
|
||||
- Spot common patterns or contradictions
|
||||
- Note emerging trends across sources
|
||||
|
||||
3. Create Structured Summary:
|
||||
- Main findings per topic
|
||||
- Cross-cutting themes
|
||||
- Emerging trends
|
||||
- Practical implications
|
||||
- Future directions
|
||||
|
||||
4. Quality Checks:
|
||||
- Ensure all topics are covered
|
||||
- Verify accuracy of connections
|
||||
- Confirm clarity of insights
|
||||
- Validate practical relevance
|
||||
|
||||
Present the summary in a clear, structured format with sections for findings, patterns, trends, and implications.""",
|
||||
expected_output="""A comprehensive research synthesis containing:
|
||||
- Detailed findings from each search topic
|
||||
- Cross-topic patterns and relationships
|
||||
- Emerging trends and their implications
|
||||
- Practical applications and future directions""",
|
||||
agent=summary_agent, # Use the specialized summary agent
|
||||
async_execution=False, # Run synchronously after search tasks
|
||||
callback=async_callback
|
||||
)
|
||||
|
||||
# First run parallel search tasks
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=parallel_tasks, # Only run search tasks first
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
search_results = await agents.astart()
|
||||
print(f"Search Tasks Results: {search_results}")
|
||||
|
||||
# Create task objects with results for context
|
||||
completed_tasks = []
|
||||
for i, topic in enumerate(search_topics):
|
||||
task = Task(
|
||||
name=f"search_task_{i}_result",
|
||||
description=f"Search results for: {topic}",
|
||||
expected_output="Search results from previous task",
|
||||
agent=async_agent,
|
||||
result=search_results["task_results"][i]
|
||||
)
|
||||
completed_tasks.append(task)
|
||||
|
||||
# Update summary task with context from search results
|
||||
summary_task.context = completed_tasks
|
||||
|
||||
# Run summarization task with summary agent
|
||||
summary_agents = PraisonAIAgents(
|
||||
agents=[summary_agent], # Use summary agent for synthesis
|
||||
tasks=[summary_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
summary_result = await summary_agents.astart()
|
||||
print(f"Summary Task Result: {summary_result}")
|
||||
|
||||
# Return results in a serializable format
|
||||
return {
|
||||
"search_results": {
|
||||
"task_status": search_results["task_status"],
|
||||
"task_results": [str(result) if result else None for result in search_results["task_results"]]
|
||||
},
|
||||
"summary": str(summary_result),
|
||||
"topics": search_topics
|
||||
}
|
||||
|
||||
# 7. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
print("Starting Async AI Agents Examples...")
|
||||
|
||||
try:
|
||||
# Run different async patterns
|
||||
await run_single_task()
|
||||
await run_parallel_tasks()
|
||||
except Exception as e:
|
||||
print(f"Error in main execution: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,141 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
def my_callback(output):
|
||||
print(f"Callback Task output: {output}")
|
||||
|
||||
def internet_search_tool(query) -> list:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles and URLs.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
tools=[internet_search_tool],
|
||||
llm="gpt-4o",
|
||||
markdown=True,
|
||||
reflect_llm="gpt-4o",
|
||||
min_reflect=2,
|
||||
max_reflect=4
|
||||
)
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
verbose=True,
|
||||
allow_delegation=True,
|
||||
llm="gpt-4o",
|
||||
tools=[],
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher,
|
||||
tools=[internet_search_tool]
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.
|
||||
Also, call the get_weather tool to get the weather in Paris.""",
|
||||
expected_output="A blog post of at least 4 paragraphs, and weather in Paris",
|
||||
agent=writer,
|
||||
context=[task1],
|
||||
callback=my_callback,
|
||||
tools=[]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="json_task",
|
||||
description="""Create a json object with a title of "My Task" and content of "My content".""",
|
||||
expected_output="""JSON output with title and content""",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="save_output_task",
|
||||
description="""Save the AI blog post to a file""",
|
||||
expected_output="""File saved successfully""",
|
||||
agent=writer,
|
||||
context=[task2],
|
||||
output_file='outputs/ai_blog_post.txt',
|
||||
create_directory=True
|
||||
)
|
||||
|
||||
# Create and run agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=False,
|
||||
process="sequential", # "sequential" or "hierarchical"
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
|
||||
# Print results and error summary
|
||||
print("\n=== Task Results ===")
|
||||
for task_id, task_status in result['task_status'].items():
|
||||
print(f"Task {task_id}: {task_status}")
|
||||
if task_result := result['task_results'].get(task_id):
|
||||
print(f"Output: {task_result.raw[:200]}...") # Show first 200 chars
|
||||
|
||||
# Print task details
|
||||
print("\n=== Task Details ===")
|
||||
for i in range(4):
|
||||
print(agents.get_task_details(i))
|
||||
|
||||
# Print agent details
|
||||
print("\n=== Agent Details ===")
|
||||
print(agents.get_agent_details('Researcher'))
|
||||
print(agents.get_agent_details('Writer'))
|
||||
|
||||
# Print any errors
|
||||
if error_logs:
|
||||
print("\n=== Error Summary ===")
|
||||
for err in error_logs:
|
||||
print(f"- {err}")
|
||||
if "parsing self-reflection json" in err:
|
||||
print(" Reason: The self-reflection JSON response was not valid JSON.")
|
||||
elif "Error: Task with ID" in err:
|
||||
print(" Reason: Task ID referenced does not exist.")
|
||||
elif "saving task output to file" in err:
|
||||
print(" Reason: Possible file permissions or invalid path.")
|
||||
else:
|
||||
print(" Reason not identified")
|
||||
@@ -1,192 +0,0 @@
|
||||
import os
|
||||
import logging
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.text import Text
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s %(filename)s:%(lineno)d %(levelname)s %(message)s",
|
||||
datefmt="[%X]"
|
||||
)
|
||||
|
||||
def my_callback(output):
|
||||
logging.info(f"Callback function called after task execution: {output.description}")
|
||||
logging.info(f"Task output: {output}")
|
||||
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
def internet_search_tool(query):
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles and URLs.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
def main():
|
||||
# Make sure OPENAI_API_KEY is set
|
||||
if not os.environ.get("OPENAI_API_KEY"):
|
||||
raise ValueError("Please set OPENAI_API_KEY environment variable")
|
||||
|
||||
# Define tools
|
||||
internet_search_tool = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "internet_search_tool",
|
||||
"description": "Use this to perform search queries",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {"type": "string"},
|
||||
},
|
||||
"required": ["query"],
|
||||
},
|
||||
},
|
||||
}
|
||||
get_weather_tool = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"description": "Get the weather for a location",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {"type": "string"},
|
||||
},
|
||||
"required": ["location"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
tools=[internet_search_tool],
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
verbose=True,
|
||||
allow_delegation=True,
|
||||
llm="gpt-4o",
|
||||
tools=[get_weather_tool],
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher,
|
||||
tools=[internet_search_tool]
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.
|
||||
Also, call the get_weather tool to get the weather in Paris.""",
|
||||
expected_output="A blog post of at least 4 paragraphs, and weather in Paris",
|
||||
agent=writer,
|
||||
context=[task1],
|
||||
callback=my_callback,
|
||||
tools=[get_weather_tool]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="json_task",
|
||||
description="""Create a json object with a title of "My Task" and content of "My content".""",
|
||||
expected_output="""JSON output with title and content""",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="save_output_task",
|
||||
description="""Save the AI blog post to a file""",
|
||||
expected_output="""File saved successfully""",
|
||||
agent=writer,
|
||||
context=[task2],
|
||||
output_file='outputs/ai_blog_post.txt',
|
||||
create_directory=True
|
||||
)
|
||||
|
||||
# Create and run agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=False,
|
||||
process="sequential", # "sequential" or "hierarchical"
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
|
||||
# Print results and error summary
|
||||
console = Console()
|
||||
|
||||
# Print task results
|
||||
console.print("\n=== Task Results ===")
|
||||
for task_id, task_status in result['task_status'].items():
|
||||
console.print(f"Task {task_id}: {task_status}")
|
||||
if task_result := result['task_results'].get(task_id):
|
||||
console.print(f"Output: {task_result.raw[:200]}...") # Show first 200 chars
|
||||
|
||||
# Print task details
|
||||
console.print("\n=== Task Details ===")
|
||||
for i in range(4):
|
||||
console.print(agents.get_task_details(i))
|
||||
|
||||
# Print agent details
|
||||
console.print("\n=== Agent Details ===")
|
||||
console.print(agents.get_agent_details('Researcher'))
|
||||
console.print(agents.get_agent_details('Writer'))
|
||||
|
||||
# Print any errors
|
||||
if error_logs:
|
||||
console.print(Panel.fit(Text("Errors Encountered:", style="bold red"), title="Error Summary", border_style="red"))
|
||||
for err in error_logs:
|
||||
console.print(f"- {err}")
|
||||
if "parsing self-reflection json" in err:
|
||||
console.print(" Reason: The self-reflection JSON response was not valid JSON.")
|
||||
elif "Error: Task with ID" in err:
|
||||
console.print(" Reason: Task ID referenced does not exist.")
|
||||
elif "saving task output to file" in err:
|
||||
console.print(" Reason: Possible file permissions or invalid path.")
|
||||
else:
|
||||
console.print(" Reason not identified")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,74 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from typing import List, Dict
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
# 1. Tool
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles, URLs, and snippets.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
# 2. Agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 3. Tasks
|
||||
collect_task = Task(
|
||||
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
|
||||
expected_output="List of search results with titles, URLs, and snippets.",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
is_start=True,
|
||||
next_tasks=["validate_data"]
|
||||
)
|
||||
|
||||
validate_task = Task(
|
||||
description="""Validate the collected data. Check if:
|
||||
1. At least 5 results are returned.
|
||||
2. Each result contains a title and a URL.
|
||||
Return validation_result as 'valid' or 'invalid' only no other text.""",
|
||||
expected_output="Validation result indicating if data is valid or invalid.",
|
||||
agent=data_agent,
|
||||
name="validate_data",
|
||||
task_type="decision",
|
||||
condition={
|
||||
"valid": [], # End the workflow on valid data
|
||||
"invalid": ["collect_data"] # Retry data collection on invalid data
|
||||
},
|
||||
)
|
||||
|
||||
# 4. Workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[collect_task, validate_task],
|
||||
verbose=1,
|
||||
process="workflow"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
@@ -0,0 +1,204 @@
|
||||
from praisonaiagents import (
|
||||
Agent,
|
||||
Task,
|
||||
PraisonAIAgents,
|
||||
error_logs,
|
||||
register_display_callback,
|
||||
sync_display_callbacks,
|
||||
async_display_callbacks
|
||||
)
|
||||
from duckduckgo_search import DDGS
|
||||
from rich.console import Console
|
||||
import json
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Callback functions for different display types
|
||||
def interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
"""Callback for display_interaction"""
|
||||
logging.info(f"""
|
||||
=== INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Markdown: {markdown}
|
||||
""")
|
||||
|
||||
def error_callback(message=None):
|
||||
"""Callback for display_error"""
|
||||
logging.error(f"""
|
||||
=== ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def tool_call_callback(message=None):
|
||||
"""Callback for display_tool_call"""
|
||||
logging.info(f"""
|
||||
=== TOOL CALL ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def instruction_callback(message=None):
|
||||
"""Callback for display_instruction"""
|
||||
logging.info(f"""
|
||||
=== INSTRUCTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def self_reflection_callback(message=None):
|
||||
"""Callback for display_self_reflection"""
|
||||
logging.info(f"""
|
||||
=== SELF REFLECTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def generating_callback(content=None, elapsed_time=None):
|
||||
"""Callback for display_generating"""
|
||||
logging.info(f"""
|
||||
=== GENERATING ===
|
||||
Time: {datetime.now()}
|
||||
Content: {content}
|
||||
Elapsed Time: {elapsed_time}
|
||||
""")
|
||||
|
||||
# Register all callbacks
|
||||
register_display_callback('interaction', interaction_callback)
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
register_display_callback('instruction', instruction_callback)
|
||||
register_display_callback('self_reflection', self_reflection_callback)
|
||||
# register_display_callback('generating', generating_callback)
|
||||
|
||||
def task_callback(output):
|
||||
"""Callback for task completion"""
|
||||
logging.info(f"""
|
||||
=== TASK COMPLETED ===
|
||||
Time: {datetime.now()}
|
||||
Description: {output.description}
|
||||
Agent: {output.agent}
|
||||
Output: {output.raw[:200]}...
|
||||
""")
|
||||
|
||||
def internet_search_tool(query) -> list:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles and URLs.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
def main():
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
tools=[internet_search_tool],
|
||||
llm="gpt-4o",
|
||||
markdown=True,
|
||||
reflect_llm="gpt-4o",
|
||||
min_reflect=2,
|
||||
max_reflect=4
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
verbose=True,
|
||||
allow_delegation=True,
|
||||
llm="gpt-4o",
|
||||
tools=[],
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks with callbacks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher,
|
||||
tools=[internet_search_tool],
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.""",
|
||||
expected_output="A blog post of at least 4 paragraphs",
|
||||
agent=writer,
|
||||
context=[task1],
|
||||
callback=task_callback,
|
||||
tools=[]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="json_task",
|
||||
description="""Create a json object with a title of "My Task" and content of "My content".""",
|
||||
expected_output="""JSON output with title and content""",
|
||||
agent=researcher,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="save_output_task",
|
||||
description="""Save the AI blog post to a file""",
|
||||
expected_output="""File saved successfully""",
|
||||
agent=writer,
|
||||
context=[task2],
|
||||
output_file='test.txt',
|
||||
create_directory=True,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
# Create and run agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=True,
|
||||
process="sequential",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -0,0 +1,59 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create Vision Analysis Agent
|
||||
vision_agent = Agent(
|
||||
name="VisionAnalyst",
|
||||
role="Computer Vision Specialist",
|
||||
goal="Analyze images and videos to extract meaningful information",
|
||||
backstory="""You are an expert in computer vision and image analysis.
|
||||
You excel at describing images, detecting objects, and understanding visual content.""",
|
||||
llm="gpt-4o-mini",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 1. Task with Image URL
|
||||
task1 = Task(
|
||||
name="analyze_landmark",
|
||||
description="Describe this famous landmark and its architectural features.",
|
||||
expected_output="Detailed description of the landmark's architecture and significance",
|
||||
agent=vision_agent,
|
||||
images=["https://upload.wikimedia.org/wikipedia/commons/b/bf/Krakow_-_Kosciol_Mariacki.jpg"]
|
||||
)
|
||||
|
||||
# 2. Task with Local Image File
|
||||
task2 = Task(
|
||||
name="analyze_local_image",
|
||||
description="What objects can you see in this image? Describe their arrangement.",
|
||||
expected_output="Detailed description of objects and their spatial relationships",
|
||||
agent=vision_agent,
|
||||
images=["image.jpg"]
|
||||
)
|
||||
|
||||
# 3. Task with Video File
|
||||
task3 = Task(
|
||||
name="analyze_video",
|
||||
description="""Watch this video and provide:
|
||||
1. A summary of the main events
|
||||
2. Key objects and people visible
|
||||
3. Any text or important information shown
|
||||
4. The overall context and setting""",
|
||||
expected_output="Comprehensive analysis of the video content",
|
||||
agent=vision_agent,
|
||||
images=["video.mp4"]
|
||||
)
|
||||
|
||||
# Create PraisonAIAgents instance
|
||||
agents = PraisonAIAgents(
|
||||
agents=[vision_agent],
|
||||
tasks=[task1, task2, task3],
|
||||
process="sequential",
|
||||
verbose=1
|
||||
)
|
||||
|
||||
# Run all tasks
|
||||
result = agents.start()
|
||||
|
||||
# Print results
|
||||
for task_id, task_result in result["task_results"].items():
|
||||
print(f"\nTask {task_id} Result:")
|
||||
print(task_result.raw)
|
||||
@@ -16,6 +16,9 @@ from .main import (
|
||||
display_generating,
|
||||
clean_triple_backticks,
|
||||
error_logs,
|
||||
register_display_callback,
|
||||
sync_display_callbacks,
|
||||
async_display_callbacks,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
@@ -32,4 +35,7 @@ __all__ = [
|
||||
'display_generating',
|
||||
'clean_triple_backticks',
|
||||
'error_logs',
|
||||
'register_display_callback',
|
||||
'sync_display_callbacks',
|
||||
'async_display_callbacks',
|
||||
]
|
||||
@@ -1,9 +1,12 @@
|
||||
import logging
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import List, Optional, Any, Dict, Union, Literal
|
||||
from rich.console import Console
|
||||
from rich.live import Live
|
||||
from openai import AsyncOpenAI
|
||||
from ..main import (
|
||||
display_error,
|
||||
display_tool_call,
|
||||
@@ -17,20 +20,130 @@ from ..main import (
|
||||
)
|
||||
|
||||
class Agent:
|
||||
def _generate_tool_definition(self, function_name):
|
||||
"""
|
||||
Generate a tool definition from a function name by inspecting the function.
|
||||
"""
|
||||
logging.debug(f"Attempting to generate tool definition for: {function_name}")
|
||||
|
||||
# First try to get the tool definition if it exists
|
||||
tool_def_name = f"{function_name}_definition"
|
||||
tool_def = globals().get(tool_def_name)
|
||||
logging.debug(f"Looking for {tool_def_name} in globals: {tool_def is not None}")
|
||||
|
||||
if not tool_def:
|
||||
import __main__
|
||||
tool_def = getattr(__main__, tool_def_name, None)
|
||||
logging.debug(f"Looking for {tool_def_name} in __main__: {tool_def is not None}")
|
||||
|
||||
if tool_def:
|
||||
logging.debug(f"Found tool definition: {tool_def}")
|
||||
return tool_def
|
||||
|
||||
# Try to find the function in the agent's tools list first
|
||||
func = None
|
||||
for tool in self.tools:
|
||||
if callable(tool) and getattr(tool, '__name__', '') == function_name:
|
||||
func = tool
|
||||
break
|
||||
|
||||
logging.debug(f"Looking for {function_name} in agent tools: {func is not None}")
|
||||
|
||||
# If not found in tools, try globals and main
|
||||
if not func:
|
||||
func = globals().get(function_name)
|
||||
logging.debug(f"Looking for {function_name} in globals: {func is not None}")
|
||||
|
||||
if not func:
|
||||
import __main__
|
||||
func = getattr(__main__, function_name, None)
|
||||
logging.debug(f"Looking for {function_name} in __main__: {func is not None}")
|
||||
|
||||
if not func or not callable(func):
|
||||
logging.debug(f"Function {function_name} not found or not callable")
|
||||
return None
|
||||
|
||||
import inspect
|
||||
sig = inspect.signature(func)
|
||||
logging.debug(f"Function signature: {sig}")
|
||||
|
||||
parameters = {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
|
||||
# Parse docstring for parameter descriptions
|
||||
docstring = inspect.getdoc(func)
|
||||
logging.debug(f"Function docstring: {docstring}")
|
||||
|
||||
param_descriptions = {}
|
||||
if docstring:
|
||||
import re
|
||||
param_section = re.split(r'\s*Args:\s*', docstring)
|
||||
logging.debug(f"Param section split: {param_section}")
|
||||
if len(param_section) > 1:
|
||||
param_lines = param_section[1].split('\n')
|
||||
for line in param_lines:
|
||||
line = line.strip()
|
||||
if line and ':' in line:
|
||||
param_name, param_desc = line.split(':', 1)
|
||||
param_descriptions[param_name.strip()] = param_desc.strip()
|
||||
|
||||
logging.debug(f"Parameter descriptions: {param_descriptions}")
|
||||
|
||||
for name, param in sig.parameters.items():
|
||||
param_type = "string" # Default type
|
||||
if param.annotation != inspect.Parameter.empty:
|
||||
if param.annotation == int:
|
||||
param_type = "integer"
|
||||
elif param.annotation == float:
|
||||
param_type = "number"
|
||||
elif param.annotation == bool:
|
||||
param_type = "boolean"
|
||||
elif param.annotation == list:
|
||||
param_type = "array"
|
||||
elif param.annotation == dict:
|
||||
param_type = "object"
|
||||
|
||||
param_info = {"type": param_type}
|
||||
if name in param_descriptions:
|
||||
param_info["description"] = param_descriptions[name]
|
||||
|
||||
parameters["properties"][name] = param_info
|
||||
if param.default == inspect.Parameter.empty:
|
||||
parameters["required"].append(name)
|
||||
|
||||
logging.debug(f"Generated parameters: {parameters}")
|
||||
|
||||
# Extract description from docstring
|
||||
description = docstring.split('\n')[0] if docstring else f"Function {function_name}"
|
||||
|
||||
tool_def = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": function_name,
|
||||
"description": description,
|
||||
"parameters": parameters
|
||||
}
|
||||
}
|
||||
logging.debug(f"Generated tool definition: {tool_def}")
|
||||
return tool_def
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
role: str,
|
||||
goal: str,
|
||||
backstory: str,
|
||||
llm: Optional[Union[str, Any]] = "gpt-4o-mini",
|
||||
llm: Optional[Union[str, Any]] = "gpt-4o",
|
||||
tools: Optional[List[Any]] = None,
|
||||
function_calling_llm: Optional[Any] = None,
|
||||
max_iter: int = 20,
|
||||
max_rpm: Optional[int] = None,
|
||||
max_execution_time: Optional[int] = None,
|
||||
memory: bool = True,
|
||||
verbose: bool = False,
|
||||
verbose: bool = True,
|
||||
allow_delegation: bool = False,
|
||||
step_callback: Optional[Any] = None,
|
||||
cache: bool = True,
|
||||
@@ -46,14 +159,16 @@ class Agent:
|
||||
use_system_prompt: Optional[bool] = True,
|
||||
markdown: bool = True,
|
||||
self_reflect: bool = True,
|
||||
max_reflection_iter: int = 3
|
||||
max_reflect: int = 3,
|
||||
min_reflect: int = 1,
|
||||
reflect_llm: Optional[str] = None
|
||||
):
|
||||
self.name = name
|
||||
self.role = role
|
||||
self.goal = goal
|
||||
self.backstory = backstory
|
||||
self.llm = llm
|
||||
self.tools = tools if tools else []
|
||||
self.tools = tools if tools else [] # Store original tools
|
||||
self.function_calling_llm = function_calling_llm
|
||||
self.max_iter = max_iter
|
||||
self.max_rpm = max_rpm
|
||||
@@ -76,21 +191,53 @@ class Agent:
|
||||
self.chat_history = []
|
||||
self.markdown = markdown
|
||||
self.self_reflect = self_reflect
|
||||
self.max_reflection_iter = max_reflection_iter
|
||||
self.max_reflect = max_reflect
|
||||
self.min_reflect = min_reflect
|
||||
self.reflect_llm = reflect_llm
|
||||
self.console = Console() # Create a single console instance for the agent
|
||||
|
||||
# Initialize system prompt
|
||||
self.system_prompt = f"""{self.backstory}\n
|
||||
Your Role: {self.role}\n
|
||||
Your Goal: {self.goal}
|
||||
"""
|
||||
|
||||
def execute_tool(self, function_name, arguments):
|
||||
"""
|
||||
Execute a tool dynamically based on the function name and arguments.
|
||||
"""
|
||||
logging.debug(f"{self.name} executing tool {function_name} with arguments: {arguments}")
|
||||
if function_name == "get_weather":
|
||||
location = arguments.get("location", "Unknown Location")
|
||||
return {"temperature": "25C", "condition": "Sunny", "location": location}
|
||||
elif function_name == "search_tool":
|
||||
query = arguments.get("query", "AI trends in 2024")
|
||||
return {"results": [
|
||||
{"title": "AI advancements in 2024", "link": "url1", "summary": "Lots of advancements"},
|
||||
{"title": "New trends in AI", "link": "url2", "summary": "New trends being found"}
|
||||
]}
|
||||
else:
|
||||
return f"Tool '{function_name}' is not recognized"
|
||||
|
||||
# Try to find the function in the agent's tools list first
|
||||
func = None
|
||||
for tool in self.tools:
|
||||
if callable(tool) and getattr(tool, '__name__', '') == function_name:
|
||||
func = tool
|
||||
break
|
||||
|
||||
logging.debug(f"Looking for {function_name} in agent tools: {func is not None}")
|
||||
|
||||
# If not found in tools, try globals and main
|
||||
if not func:
|
||||
func = globals().get(function_name)
|
||||
logging.debug(f"Looking for {function_name} in globals: {func is not None}")
|
||||
|
||||
if not func:
|
||||
import __main__
|
||||
func = getattr(__main__, function_name, None)
|
||||
logging.debug(f"Looking for {function_name} in __main__: {func is not None}")
|
||||
|
||||
if func and callable(func):
|
||||
try:
|
||||
return func(**arguments)
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
logging.error(f"Error executing tool {function_name}: {error_msg}")
|
||||
return {"error": error_msg}
|
||||
|
||||
error_msg = f"Tool '{function_name}' is not callable"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def clear_history(self):
|
||||
self.chat_history = []
|
||||
@@ -99,31 +246,29 @@ class Agent:
|
||||
return f"Agent(name='{self.name}', role='{self.role}', goal='{self.goal}')"
|
||||
|
||||
def _chat_completion(self, messages, temperature=0.2, tools=None, stream=True):
|
||||
console = Console()
|
||||
start_time = time.time()
|
||||
logging.debug(f"{self.name} sending messages to LLM: {messages}")
|
||||
|
||||
formatted_tools = []
|
||||
if tools is None:
|
||||
tools = self.tools
|
||||
if tools:
|
||||
for tool in tools:
|
||||
if isinstance(tool, dict):
|
||||
if isinstance(tool, str):
|
||||
# Generate tool definition for string tool names
|
||||
tool_def = self._generate_tool_definition(tool)
|
||||
if tool_def:
|
||||
formatted_tools.append(tool_def)
|
||||
else:
|
||||
logging.warning(f"Could not generate definition for tool: {tool}")
|
||||
elif isinstance(tool, dict):
|
||||
formatted_tools.append(tool)
|
||||
elif hasattr(tool, "to_openai_tool"):
|
||||
formatted_tools.append(tool.to_openai_tool())
|
||||
elif isinstance(tool, str):
|
||||
formatted_tools.append({
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tool,
|
||||
"description": f"This is a tool called {tool}",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
},
|
||||
}
|
||||
})
|
||||
elif callable(tool):
|
||||
formatted_tools.append(self._generate_tool_definition(tool.__name__))
|
||||
else:
|
||||
display_error(f"Warning: Tool {tool} not recognized")
|
||||
logging.warning(f"Tool {tool} not recognized")
|
||||
|
||||
try:
|
||||
initial_response = client.chat.completions.create(
|
||||
@@ -170,12 +315,24 @@ class Agent:
|
||||
stream=True
|
||||
)
|
||||
full_response_text = ""
|
||||
with Live(display_generating("", start_time), refresh_per_second=4) as live:
|
||||
|
||||
# Create Live display with proper configuration
|
||||
with Live(
|
||||
display_generating("", start_time),
|
||||
console=self.console,
|
||||
refresh_per_second=4,
|
||||
transient=False, # Changed to False to preserve output
|
||||
vertical_overflow="ellipsis",
|
||||
auto_refresh=True
|
||||
) as live:
|
||||
for chunk in response_stream:
|
||||
if chunk.choices[0].delta.content:
|
||||
full_response_text += chunk.choices[0].delta.content
|
||||
live.update(display_generating(full_response_text, start_time))
|
||||
|
||||
|
||||
# Clear the last generating display with a blank line
|
||||
self.console.print()
|
||||
|
||||
final_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
@@ -202,17 +359,36 @@ class Agent:
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None):
|
||||
if self.use_system_prompt:
|
||||
system_prompt = f"""{self.backstory}\n
|
||||
Your Role: {self.role}\n
|
||||
Your Goal: {self.goal}
|
||||
Your Role: {self.role}\n
|
||||
Your Goal: {self.goal}
|
||||
"""
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
|
||||
else:
|
||||
system_prompt = None
|
||||
|
||||
|
||||
messages = []
|
||||
if system_prompt:
|
||||
messages.append({"role": "system", "content": system_prompt})
|
||||
messages.extend(self.chat_history)
|
||||
messages.append({"role": "user", "content": prompt})
|
||||
|
||||
# Modify prompt if output_json is specified
|
||||
original_prompt = prompt
|
||||
if output_json:
|
||||
if isinstance(prompt, str):
|
||||
prompt += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
elif isinstance(prompt, list):
|
||||
# For multimodal prompts, append to the text content
|
||||
for item in prompt:
|
||||
if item["type"] == "text":
|
||||
item["text"] += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
break
|
||||
|
||||
if isinstance(prompt, list):
|
||||
# If we receive a multimodal prompt list, place it directly in the user message
|
||||
messages.append({"role": "user", "content": prompt})
|
||||
else:
|
||||
messages.append({"role": "user", "content": prompt})
|
||||
|
||||
final_response_text = None
|
||||
reflection_count = 0
|
||||
@@ -221,40 +397,26 @@ class Agent:
|
||||
while True:
|
||||
try:
|
||||
if self.verbose:
|
||||
display_instruction(f"Agent {self.name} is processing prompt: {prompt}")
|
||||
# Handle both string and list prompts for instruction display
|
||||
display_text = prompt
|
||||
if isinstance(prompt, list):
|
||||
# Extract text content from multimodal prompt
|
||||
display_text = next((item["text"] for item in prompt if item["type"] == "text"), "")
|
||||
|
||||
if display_text and str(display_text).strip():
|
||||
display_instruction(f"Agent {self.name} is processing prompt: {display_text}", console=self.console)
|
||||
|
||||
formatted_tools = []
|
||||
if tools:
|
||||
for tool in tools:
|
||||
if isinstance(tool, dict):
|
||||
formatted_tools.append(tool)
|
||||
elif hasattr(tool, "to_openai_tool"):
|
||||
formatted_tools.append(tool.to_openai_tool())
|
||||
elif isinstance(tool, str):
|
||||
formatted_tools.append({
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tool,
|
||||
"description": f"This is a tool called {tool}",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
},
|
||||
}
|
||||
})
|
||||
else:
|
||||
display_error(f"Warning: Tool {tool} not recognized")
|
||||
|
||||
response = self._chat_completion(messages, temperature=temperature, tools=formatted_tools if formatted_tools else None)
|
||||
response = self._chat_completion(messages, temperature=temperature, tools=tools if tools else None)
|
||||
if not response:
|
||||
return None
|
||||
|
||||
|
||||
tool_calls = getattr(response.choices[0].message, 'tool_calls', None)
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
if tool_calls:
|
||||
messages.append({
|
||||
"role": "assistant",
|
||||
"content": response.choices[0].message.content,
|
||||
"content": response_text,
|
||||
"tool_calls": tool_calls
|
||||
})
|
||||
|
||||
@@ -263,13 +425,13 @@ class Agent:
|
||||
arguments = json.loads(tool_call.function.arguments)
|
||||
|
||||
if self.verbose:
|
||||
display_tool_call(f"Agent {self.name} is calling function '{function_name}' with arguments: {arguments}")
|
||||
display_tool_call(f"Agent {self.name} is calling function '{function_name}' with arguments: {arguments}", console=self.console)
|
||||
|
||||
tool_result = self.execute_tool(function_name, arguments)
|
||||
|
||||
if tool_result:
|
||||
if self.verbose:
|
||||
display_tool_call(f"Function '{function_name}' returned: {tool_result}")
|
||||
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=self.console)
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
@@ -286,29 +448,45 @@ class Agent:
|
||||
if not response:
|
||||
return None
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
else:
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
# Handle output_json if specified
|
||||
if output_json:
|
||||
try:
|
||||
# Clean the response text to get only JSON
|
||||
cleaned_json = self.clean_json_output(response_text)
|
||||
# Parse into Pydantic model
|
||||
parsed_model = output_json.model_validate_json(cleaned_json)
|
||||
# Add to chat history and return
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown,
|
||||
generation_time=time.time() - start_time, console=self.console)
|
||||
return parsed_model
|
||||
except Exception as e:
|
||||
display_error(f"Failed to parse response as {output_json.__name__}: {e}")
|
||||
return None
|
||||
|
||||
if not self.self_reflect:
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
logging.info(f"Agent {self.name} final response: {response_text}")
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time)
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
reflection_prompt = f"""
|
||||
Reflect on your previous response: '{response_text}'.
|
||||
Identify any flaws, improvements, or actions.
|
||||
Provide a "satisfactory" status ('yes' or 'no').
|
||||
Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
Reflect on your previous response: '{response_text}'.
|
||||
Identify any flaws, improvements, or actions.
|
||||
Provide a "satisfactory" status ('yes' or 'no').
|
||||
Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
"""
|
||||
logging.debug(f"{self.name} reflection attempt {reflection_count+1}, sending prompt: {reflection_prompt}")
|
||||
messages.append({"role": "user", "content": reflection_prompt})
|
||||
|
||||
try:
|
||||
reflection_response = client.beta.chat.completions.parse(
|
||||
model=self.llm,
|
||||
model=self.reflect_llm if self.reflect_llm else self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
response_format=ReflectionOutput
|
||||
@@ -317,35 +495,193 @@ class Agent:
|
||||
reflection_output = reflection_response.choices[0].message.parsed
|
||||
|
||||
if self.verbose:
|
||||
display_self_reflection(f"Agent {self.name} self reflection: reflection='{reflection_output.reflection}' satisfactory='{reflection_output.satisfactory}'")
|
||||
display_self_reflection(f"Agent {self.name} self reflection (using {self.reflect_llm if self.reflect_llm else self.llm}): reflection='{reflection_output.reflection}' satisfactory='{reflection_output.satisfactory}'", console=self.console)
|
||||
|
||||
messages.append({"role": "assistant", "content": f"Self Reflection: {reflection_output.reflection} Satisfactory?: {reflection_output.satisfactory}"})
|
||||
|
||||
if reflection_output.satisfactory == "yes":
|
||||
# Only consider satisfactory after minimum reflections
|
||||
if reflection_output.satisfactory == "yes" and reflection_count >= self.min_reflect - 1:
|
||||
if self.verbose:
|
||||
display_self_reflection("Agent marked the response as satisfactory")
|
||||
display_self_reflection("Agent marked the response as satisfactory after meeting minimum reflections", console=self.console)
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time)
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
logging.debug(f"{self.name} reflection not satisfactory, requesting regeneration.")
|
||||
# Check if we've hit max reflections
|
||||
if reflection_count >= self.max_reflect - 1:
|
||||
if self.verbose:
|
||||
display_self_reflection("Maximum reflection count reached, returning current response", console=self.console)
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
logging.debug(f"{self.name} reflection count {reflection_count + 1}, continuing reflection process")
|
||||
messages.append({"role": "user", "content": "Now regenerate your response using the reflection you made"})
|
||||
response = self._chat_completion(messages, temperature=temperature, tools=None, stream=True)
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
reflection_count += 1
|
||||
continue # Continue the loop for more reflections
|
||||
|
||||
except Exception as e:
|
||||
display_error(f"Error in parsing self-reflection json {e}. Retrying")
|
||||
display_error(f"Error in parsing self-reflection json {e}. Retrying", console=self.console)
|
||||
logging.error("Reflection parsing failed.", exc_info=True)
|
||||
messages.append({"role": "assistant", "content": f"Self Reflection failed."})
|
||||
reflection_count += 1
|
||||
continue # Continue even after error to try again
|
||||
|
||||
reflection_count += 1
|
||||
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
|
||||
if self.verbose:
|
||||
logging.info(f"Agent {self.name} final response: {response_text}")
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time)
|
||||
return response_text
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat: {e}")
|
||||
return None
|
||||
display_error(f"Error in chat: {e}", console=self.console)
|
||||
return None
|
||||
|
||||
def clean_json_output(self, output: str) -> str:
|
||||
"""Clean and extract JSON from response text."""
|
||||
cleaned = output.strip()
|
||||
# Remove markdown code blocks if present
|
||||
if cleaned.startswith("```json"):
|
||||
cleaned = cleaned[len("```json"):].strip()
|
||||
if cleaned.startswith("```"):
|
||||
cleaned = cleaned[len("```"):].strip()
|
||||
if cleaned.endswith("```"):
|
||||
cleaned = cleaned[:-3].strip()
|
||||
return cleaned
|
||||
|
||||
async def achat(self, prompt, temperature=0.2, tools=None, output_json=None):
|
||||
"""Async version of chat method"""
|
||||
try:
|
||||
# Build system prompt
|
||||
system_prompt = self.system_prompt
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
|
||||
|
||||
# Build messages
|
||||
if isinstance(prompt, str):
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt + ("\nReturn ONLY a valid JSON object. No other text or explanation." if output_json else "")}
|
||||
]
|
||||
else:
|
||||
# For multimodal prompts
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
if output_json:
|
||||
# Add JSON instruction to text content
|
||||
for item in messages[-1]["content"]:
|
||||
if item["type"] == "text":
|
||||
item["text"] += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
break
|
||||
|
||||
# Format tools if provided
|
||||
formatted_tools = []
|
||||
if tools:
|
||||
for tool in tools:
|
||||
if isinstance(tool, str):
|
||||
tool_def = self._generate_tool_definition(tool)
|
||||
if tool_def:
|
||||
formatted_tools.append(tool_def)
|
||||
elif isinstance(tool, dict):
|
||||
formatted_tools.append(tool)
|
||||
elif hasattr(tool, "to_openai_tool"):
|
||||
formatted_tools.append(tool.to_openai_tool())
|
||||
elif callable(tool):
|
||||
formatted_tools.append(self._generate_tool_definition(tool.__name__))
|
||||
|
||||
# Create async OpenAI client
|
||||
async_client = AsyncOpenAI()
|
||||
|
||||
# Make the API call based on the type of request
|
||||
if tools:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools
|
||||
)
|
||||
return await self._achat_completion(response, tools)
|
||||
elif output_json:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
result = response.choices[0].message.content
|
||||
# Clean and parse the JSON response
|
||||
cleaned_json = self.clean_json_output(result)
|
||||
try:
|
||||
parsed = json.loads(cleaned_json)
|
||||
return output_json(**parsed)
|
||||
except Exception as e:
|
||||
display_error(f"Error parsing JSON response: {e}")
|
||||
return None
|
||||
else:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature
|
||||
)
|
||||
return response.choices[0].message.content
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
return None
|
||||
|
||||
async def _achat_completion(self, response, tools):
|
||||
"""Async version of _chat_completion method"""
|
||||
try:
|
||||
message = response.choices[0].message
|
||||
if not hasattr(message, 'tool_calls') or not message.tool_calls:
|
||||
return message.content
|
||||
|
||||
results = []
|
||||
for tool_call in message.tool_calls:
|
||||
try:
|
||||
function_name = tool_call.function.name
|
||||
arguments = json.loads(tool_call.function.arguments)
|
||||
|
||||
# Find the matching tool
|
||||
tool = next((t for t in tools if t.__name__ == function_name), None)
|
||||
if not tool:
|
||||
display_error(f"Tool {function_name} not found")
|
||||
continue
|
||||
|
||||
# Check if the tool is async
|
||||
if asyncio.iscoroutinefunction(tool):
|
||||
result = await tool(**arguments)
|
||||
else:
|
||||
# Run sync function in executor to avoid blocking
|
||||
loop = asyncio.get_event_loop()
|
||||
result = await loop.run_in_executor(None, lambda: tool(**arguments))
|
||||
|
||||
results.append(result)
|
||||
except Exception as e:
|
||||
display_error(f"Error executing tool {function_name}: {e}")
|
||||
results.append(None)
|
||||
|
||||
# If we have results, format them into a response
|
||||
if results:
|
||||
formatted_results = "\n".join([str(r) for r in results if r is not None])
|
||||
if formatted_results:
|
||||
messages = [
|
||||
{"role": "system", "content": self.system_prompt},
|
||||
{"role": "assistant", "content": "Here are the tool results:"},
|
||||
{"role": "user", "content": formatted_results + "\nPlease process these results and provide a final response."}
|
||||
]
|
||||
try:
|
||||
async_client = AsyncOpenAI()
|
||||
final_response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=0.2
|
||||
)
|
||||
return final_response.choices[0].message.content
|
||||
except Exception as e:
|
||||
display_error(f"Error in final chat completion: {e}")
|
||||
return formatted_results
|
||||
return formatted_results
|
||||
return None
|
||||
except Exception as e:
|
||||
display_error(f"Error in _achat_completion: {e}")
|
||||
return None
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
import time
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict, Optional, List
|
||||
from pydantic import BaseModel
|
||||
from rich.text import Text
|
||||
from rich.panel import Panel
|
||||
@@ -10,6 +10,35 @@ from rich.console import Console
|
||||
from ..main import display_error, TaskOutput, error_logs, client
|
||||
from ..agent.agent import Agent
|
||||
from ..task.task import Task
|
||||
from ..process.process import Process, LoopItems
|
||||
import asyncio
|
||||
|
||||
def encode_file_to_base64(file_path: str) -> str:
|
||||
"""Base64-encode a file."""
|
||||
import base64
|
||||
with open(file_path, "rb") as f:
|
||||
return base64.b64encode(f.read()).decode("utf-8")
|
||||
|
||||
def process_video(video_path: str, seconds_per_frame=2):
|
||||
"""Split video into frames (base64-encoded)."""
|
||||
import cv2
|
||||
import base64
|
||||
base64_frames = []
|
||||
video = cv2.VideoCapture(video_path)
|
||||
total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||
fps = video.get(cv2.CAP_PROP_FPS)
|
||||
frames_to_skip = int(fps * seconds_per_frame)
|
||||
curr_frame = 0
|
||||
while curr_frame < total_frames:
|
||||
video.set(cv2.CAP_PROP_POS_FRAMES, curr_frame)
|
||||
success, frame = video.read()
|
||||
if not success:
|
||||
break
|
||||
_, buffer = cv2.imencode(".jpg", frame)
|
||||
base64_frames.append(base64.b64encode(buffer).decode("utf-8"))
|
||||
curr_frame += frames_to_skip
|
||||
video.release()
|
||||
return base64_frames
|
||||
|
||||
class PraisonAIAgents:
|
||||
def __init__(self, agents, tasks, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None):
|
||||
@@ -28,6 +57,7 @@ class PraisonAIAgents:
|
||||
for task in tasks:
|
||||
self.add_task(task)
|
||||
task.status = "not started"
|
||||
self._state = {} # Add state storage at PraisonAIAgents level
|
||||
|
||||
def add_task(self, task):
|
||||
task_id = self.task_id_counter
|
||||
@@ -53,19 +83,33 @@ class PraisonAIAgents:
|
||||
return True
|
||||
return len(agent_output.strip()) > 0
|
||||
|
||||
def execute_task(self, task_id):
|
||||
async def aexecute_task(self, task_id):
|
||||
"""Async version of execute_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
task = self.tasks[task_id]
|
||||
|
||||
# Only import multimodal dependencies if task has images
|
||||
if task.images and task.status == "not started":
|
||||
try:
|
||||
import cv2
|
||||
import base64
|
||||
from moviepy import VideoFileClip
|
||||
except ImportError as e:
|
||||
display_error(f"Error: Missing required dependencies for image/video processing: {e}")
|
||||
display_error("Please install with: pip install opencv-python moviepy")
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
if task.status == "not started":
|
||||
task.status = "in progress"
|
||||
|
||||
executor_agent = task.agent
|
||||
|
||||
task_prompt = f"""
|
||||
You need to do the following task: {task.description}.
|
||||
Expected Output: {task.expected_output}.
|
||||
You need to do the following task: {task.description}.
|
||||
Expected Output: {task.expected_output}.
|
||||
"""
|
||||
if task.context:
|
||||
context_results = ""
|
||||
@@ -83,7 +127,47 @@ class PraisonAIAgents:
|
||||
if self.verbose >= 2:
|
||||
logging.info(f"Executing task {task_id}: {task.description} using {executor_agent.name}")
|
||||
logging.debug(f"Starting execution of task {task_id} with prompt:\n{task_prompt}")
|
||||
agent_output = executor_agent.chat(task_prompt, tools=task.tools)
|
||||
|
||||
if task.images:
|
||||
def _get_multimodal_message(text_prompt, images):
|
||||
content = [{"type": "text", "text": text_prompt}]
|
||||
|
||||
for img in images:
|
||||
# If local file path for a valid image
|
||||
if os.path.exists(img):
|
||||
ext = os.path.splitext(img)[1].lower()
|
||||
# If it's a .mp4, convert to frames
|
||||
if ext == ".mp4":
|
||||
frames = process_video(img, seconds_per_frame=1)
|
||||
content.append({"type": "text", "text": "These are frames from the video."})
|
||||
for f in frames:
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {"url": f"data:image/jpg;base64,{f}"}
|
||||
})
|
||||
else:
|
||||
encoded = encode_file_to_base64(img)
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": f"data:image/{ext.lstrip('.')};base64,{encoded}"
|
||||
}
|
||||
})
|
||||
else:
|
||||
# Treat as a remote URL
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {"url": img}
|
||||
})
|
||||
return content
|
||||
|
||||
agent_output = await executor_agent.achat(
|
||||
_get_multimodal_message(task_prompt, task.images),
|
||||
tools=task.tools
|
||||
)
|
||||
else:
|
||||
agent_output = await executor_agent.achat(task_prompt, tools=task.tools)
|
||||
|
||||
if agent_output:
|
||||
task_output = TaskOutput(
|
||||
description=task.description,
|
||||
@@ -120,6 +204,83 @@ class PraisonAIAgents:
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
async def arun_task(self, task_id):
|
||||
"""Async version of run_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
task = self.tasks[task_id]
|
||||
if task.status == "completed":
|
||||
logging.info(f"Task with ID {task_id} is already completed")
|
||||
return
|
||||
|
||||
retries = 0
|
||||
while task.status != "completed" and retries < self.max_retries:
|
||||
logging.debug(f"Attempt {retries+1} for task {task_id}")
|
||||
if task.status in ["not started", "in progress"]:
|
||||
task_output = await self.aexecute_task(task_id)
|
||||
if task_output and self.completion_checker(task, task_output.raw):
|
||||
task.status = "completed"
|
||||
if task.callback:
|
||||
await task.execute_callback(task_output)
|
||||
self.save_output_to_file(task, task_output)
|
||||
if self.verbose >= 1:
|
||||
logging.info(f"Task {task_id} completed successfully.")
|
||||
else:
|
||||
task.status = "in progress"
|
||||
if self.verbose >= 1:
|
||||
logging.info(f"Task {task_id} not completed, retrying")
|
||||
await asyncio.sleep(1)
|
||||
retries += 1
|
||||
else:
|
||||
if task.status == "failed":
|
||||
logging.info("Task is failed, resetting to in-progress for another try...")
|
||||
task.status = "in progress"
|
||||
else:
|
||||
logging.info("Invalid Task status")
|
||||
break
|
||||
|
||||
if retries == self.max_retries and task.status != "completed":
|
||||
logging.info(f"Task {task_id} failed after {self.max_retries} retries.")
|
||||
|
||||
async def arun_all_tasks(self):
|
||||
"""Async version of run_all_tasks method"""
|
||||
process = Process(
|
||||
tasks=self.tasks,
|
||||
agents=self.agents,
|
||||
manager_llm=self.manager_llm,
|
||||
verbose=self.verbose
|
||||
)
|
||||
|
||||
if self.process == "workflow":
|
||||
async for task_id in process.aworkflow():
|
||||
if self.tasks[task_id].async_execution:
|
||||
await self.arun_task(task_id)
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
elif self.process == "sequential":
|
||||
async for task_id in process.asequential():
|
||||
if self.tasks[task_id].async_execution:
|
||||
await self.arun_task(task_id)
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
elif self.process == "hierarchical":
|
||||
async for task_id in process.ahierarchical():
|
||||
if isinstance(task_id, Task):
|
||||
task_id = self.add_task(task_id)
|
||||
if self.tasks[task_id].async_execution:
|
||||
await self.arun_task(task_id)
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
|
||||
async def astart(self):
|
||||
"""Async version of start method"""
|
||||
await self.arun_all_tasks()
|
||||
return {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
|
||||
}
|
||||
|
||||
def save_output_to_file(self, task, task_output):
|
||||
if task.output_file:
|
||||
try:
|
||||
@@ -132,7 +293,129 @@ class PraisonAIAgents:
|
||||
except Exception as e:
|
||||
display_error(f"Error saving task output to file: {e}")
|
||||
|
||||
def execute_task(self, task_id):
|
||||
"""Synchronous version of execute_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
task = self.tasks[task_id]
|
||||
|
||||
# Only import multimodal dependencies if task has images
|
||||
if task.images and task.status == "not started":
|
||||
try:
|
||||
import cv2
|
||||
import base64
|
||||
from moviepy import VideoFileClip
|
||||
except ImportError as e:
|
||||
display_error(f"Error: Missing required dependencies for image/video processing: {e}")
|
||||
display_error("Please install with: pip install opencv-python moviepy")
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
if task.status == "not started":
|
||||
task.status = "in progress"
|
||||
|
||||
executor_agent = task.agent
|
||||
|
||||
task_prompt = f"""
|
||||
You need to do the following task: {task.description}.
|
||||
Expected Output: {task.expected_output}.
|
||||
"""
|
||||
if task.context:
|
||||
context_results = ""
|
||||
for context_task in task.context:
|
||||
if context_task.result:
|
||||
context_results += f"Result of previous task {context_task.name if context_task.name else context_task.description}: {context_task.result.raw}\n"
|
||||
else:
|
||||
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
|
||||
task_prompt += f"""
|
||||
Here are the results of previous tasks that might be useful:\n
|
||||
{context_results}
|
||||
"""
|
||||
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
|
||||
|
||||
if self.verbose >= 2:
|
||||
logging.info(f"Executing task {task_id}: {task.description} using {executor_agent.name}")
|
||||
logging.debug(f"Starting execution of task {task_id} with prompt:\n{task_prompt}")
|
||||
|
||||
if task.images:
|
||||
def _get_multimodal_message(text_prompt, images):
|
||||
content = [{"type": "text", "text": text_prompt}]
|
||||
|
||||
for img in images:
|
||||
# If local file path for a valid image
|
||||
if os.path.exists(img):
|
||||
ext = os.path.splitext(img)[1].lower()
|
||||
# If it's a .mp4, convert to frames
|
||||
if ext == ".mp4":
|
||||
frames = process_video(img, seconds_per_frame=1)
|
||||
content.append({"type": "text", "text": "These are frames from the video."})
|
||||
for f in frames:
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {"url": f"data:image/jpg;base64,{f}"}
|
||||
})
|
||||
else:
|
||||
encoded = encode_file_to_base64(img)
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": f"data:image/{ext.lstrip('.')};base64,{encoded}"
|
||||
}
|
||||
})
|
||||
else:
|
||||
# Treat as a remote URL
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {"url": img}
|
||||
})
|
||||
return content
|
||||
|
||||
agent_output = executor_agent.chat(
|
||||
_get_multimodal_message(task_prompt, task.images),
|
||||
tools=task.tools
|
||||
)
|
||||
else:
|
||||
agent_output = executor_agent.chat(task_prompt, tools=task.tools)
|
||||
|
||||
if agent_output:
|
||||
task_output = TaskOutput(
|
||||
description=task.description,
|
||||
summary=task.description[:10],
|
||||
raw=agent_output,
|
||||
agent=executor_agent.name,
|
||||
output_format="RAW"
|
||||
)
|
||||
|
||||
if task.output_json:
|
||||
cleaned = self.clean_json_output(agent_output)
|
||||
try:
|
||||
parsed = json.loads(cleaned)
|
||||
task_output.json_dict = parsed
|
||||
task_output.output_format = "JSON"
|
||||
except:
|
||||
logging.warning(f"Warning: Could not parse output of task {task_id} as JSON")
|
||||
logging.debug(f"Output that failed JSON parsing: {agent_output}")
|
||||
|
||||
if task.output_pydantic:
|
||||
cleaned = self.clean_json_output(agent_output)
|
||||
try:
|
||||
parsed = json.loads(cleaned)
|
||||
pyd_obj = task.output_pydantic(**parsed)
|
||||
task_output.pydantic = pyd_obj
|
||||
task_output.output_format = "Pydantic"
|
||||
except:
|
||||
logging.warning(f"Warning: Could not parse output of task {task_id} as Pydantic Model")
|
||||
logging.debug(f"Output that failed Pydantic parsing: {agent_output}")
|
||||
|
||||
task.result = task_output
|
||||
return task_output
|
||||
else:
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
def run_task(self, task_id):
|
||||
"""Synchronous version of run_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
@@ -171,122 +454,25 @@ class PraisonAIAgents:
|
||||
logging.info(f"Task {task_id} failed after {self.max_retries} retries.")
|
||||
|
||||
def run_all_tasks(self):
|
||||
if self.process == "sequential":
|
||||
for task_id in self.tasks:
|
||||
if self.tasks[task_id].status != "completed":
|
||||
self.run_task(task_id)
|
||||
"""Synchronous version of run_all_tasks method"""
|
||||
process = Process(
|
||||
tasks=self.tasks,
|
||||
agents=self.agents,
|
||||
manager_llm=self.manager_llm,
|
||||
verbose=self.verbose
|
||||
)
|
||||
|
||||
if self.process == "workflow":
|
||||
for task_id in process.workflow():
|
||||
self.run_task(task_id)
|
||||
elif self.process == "sequential":
|
||||
for task_id in process.sequential():
|
||||
self.run_task(task_id)
|
||||
elif self.process == "hierarchical":
|
||||
logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
|
||||
manager_agent = Agent(
|
||||
name="Manager",
|
||||
role="Project manager",
|
||||
goal="Manage the entire flow of tasks and delegate them to the right agent",
|
||||
backstory="Expert project manager to coordinate tasks among agents",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True,
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
class ManagerInstructions(BaseModel):
|
||||
task_id: int
|
||||
agent_name: str
|
||||
action: str
|
||||
|
||||
manager_task = Task(
|
||||
name="manager_task",
|
||||
description="Decide the order of tasks and which agent executes them",
|
||||
expected_output="All tasks completed successfully",
|
||||
agent=manager_agent
|
||||
)
|
||||
manager_task_id = self.add_task(manager_task)
|
||||
logging.info(f"Created manager task with ID {manager_task_id}")
|
||||
|
||||
completed_count = 0
|
||||
total_tasks = len(self.tasks) - 1
|
||||
logging.info(f"Need to complete {total_tasks} tasks (excluding manager task)")
|
||||
|
||||
while completed_count < total_tasks:
|
||||
tasks_summary = []
|
||||
for tid, tk in self.tasks.items():
|
||||
if tk.name == "manager_task":
|
||||
continue
|
||||
task_info = {
|
||||
"task_id": tid,
|
||||
"name": tk.name,
|
||||
"description": tk.description,
|
||||
"status": tk.status if tk.status else "not started",
|
||||
"agent": tk.agent.name if tk.agent else "No agent"
|
||||
}
|
||||
tasks_summary.append(task_info)
|
||||
logging.info(f"Task {tid} status: {task_info}")
|
||||
|
||||
manager_prompt = f"""
|
||||
Here is the current status of all tasks except yours (manager_task):
|
||||
{tasks_summary}
|
||||
|
||||
Provide a JSON with the structure:
|
||||
{{
|
||||
"task_id": <int>,
|
||||
"agent_name": "<string>",
|
||||
"action": "<execute or stop>"
|
||||
}}
|
||||
"""
|
||||
|
||||
try:
|
||||
logging.info("Requesting manager instructions...")
|
||||
manager_response = client.beta.chat.completions.parse(
|
||||
model=self.manager_llm,
|
||||
messages=[
|
||||
{"role": "system", "content": manager_task.description},
|
||||
{"role": "user", "content": manager_prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format=ManagerInstructions
|
||||
)
|
||||
parsed_instructions = manager_response.choices[0].message.parsed
|
||||
logging.info(f"Manager instructions: {parsed_instructions}")
|
||||
except Exception as e:
|
||||
display_error(f"Manager parse error: {e}")
|
||||
logging.error(f"Manager parse error: {str(e)}", exc_info=True)
|
||||
break
|
||||
|
||||
selected_task_id = parsed_instructions.task_id
|
||||
selected_agent_name = parsed_instructions.agent_name
|
||||
action = parsed_instructions.action
|
||||
|
||||
logging.info(f"Manager selected task_id={selected_task_id}, agent={selected_agent_name}, action={action}")
|
||||
|
||||
if action.lower() == "stop":
|
||||
logging.info("Manager decided to stop task execution")
|
||||
break
|
||||
|
||||
if selected_task_id not in self.tasks:
|
||||
error_msg = f"Manager selected invalid task id {selected_task_id}"
|
||||
display_error(error_msg)
|
||||
logging.error(error_msg)
|
||||
break
|
||||
|
||||
original_agent = self.tasks[selected_task_id].agent.name if self.tasks[selected_task_id].agent else "None"
|
||||
for a in self.agents:
|
||||
if a.name == selected_agent_name:
|
||||
self.tasks[selected_task_id].agent = a
|
||||
logging.info(f"Changed agent for task {selected_task_id} from {original_agent} to {selected_agent_name}")
|
||||
break
|
||||
|
||||
if self.tasks[selected_task_id].status != "completed":
|
||||
logging.info(f"Starting execution of task {selected_task_id}")
|
||||
self.run_task(selected_task_id)
|
||||
logging.info(f"Finished execution of task {selected_task_id}, status: {self.tasks[selected_task_id].status}")
|
||||
|
||||
if self.tasks[selected_task_id].status == "completed":
|
||||
completed_count += 1
|
||||
logging.info(f"Task {selected_task_id} completed. Total completed: {completed_count}/{total_tasks}")
|
||||
|
||||
self.tasks[manager_task.id].status = "completed"
|
||||
if self.verbose >= 1:
|
||||
logging.info("All tasks completed under manager supervision.")
|
||||
logging.info("Hierarchical task execution finished")
|
||||
for task_id in process.hierarchical():
|
||||
if isinstance(task_id, Task):
|
||||
task_id = self.add_task(task_id)
|
||||
self.run_task(task_id)
|
||||
|
||||
def get_task_status(self, task_id):
|
||||
if task_id in self.tasks:
|
||||
@@ -317,4 +503,20 @@ Provide a JSON with the structure:
|
||||
return {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
|
||||
}
|
||||
}
|
||||
|
||||
def set_state(self, key: str, value: Any) -> None:
|
||||
"""Set a state value"""
|
||||
self._state[key] = value
|
||||
|
||||
def get_state(self, key: str, default: Any = None) -> Any:
|
||||
"""Get a state value"""
|
||||
return self._state.get(key, default)
|
||||
|
||||
def update_state(self, updates: Dict) -> None:
|
||||
"""Update multiple state values"""
|
||||
self._state.update(updates)
|
||||
|
||||
def clear_state(self) -> None:
|
||||
"""Clear all state values"""
|
||||
self._state.clear()
|
||||
+252
-15
@@ -12,6 +12,7 @@ from rich.text import Text
|
||||
from rich.markdown import Markdown
|
||||
from rich.logging import RichHandler
|
||||
from rich.live import Live
|
||||
import asyncio
|
||||
|
||||
LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
|
||||
|
||||
@@ -25,43 +26,279 @@ logging.basicConfig(
|
||||
# Global list to store error logs
|
||||
error_logs = []
|
||||
|
||||
def display_interaction(message: str, response: str, markdown: bool = True, generation_time: Optional[float] = None):
|
||||
console = Console()
|
||||
if generation_time is not None:
|
||||
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
|
||||
# Separate registries for sync and async callbacks
|
||||
sync_display_callbacks = {}
|
||||
async_display_callbacks = {}
|
||||
|
||||
# At the top of the file, add display_callbacks to __all__
|
||||
__all__ = [
|
||||
'error_logs',
|
||||
'register_display_callback',
|
||||
'sync_display_callbacks',
|
||||
'async_display_callbacks',
|
||||
# ... other exports
|
||||
]
|
||||
|
||||
def register_display_callback(display_type: str, callback_fn, is_async: bool = False):
|
||||
"""Register a synchronous or asynchronous callback function for a specific display type.
|
||||
|
||||
Args:
|
||||
display_type (str): Type of display event ('interaction', 'self_reflection', etc.)
|
||||
callback_fn: The callback function to register
|
||||
is_async (bool): Whether the callback is asynchronous
|
||||
"""
|
||||
if is_async:
|
||||
async_display_callbacks[display_type] = callback_fn
|
||||
else:
|
||||
console.print(Text("Response Generation Complete", style="dim"))
|
||||
sync_display_callbacks[display_type] = callback_fn
|
||||
|
||||
async def execute_callback(display_type: str, **kwargs):
|
||||
"""Execute both sync and async callbacks for a given display type.
|
||||
|
||||
Args:
|
||||
display_type (str): Type of display event
|
||||
**kwargs: Arguments to pass to the callback functions
|
||||
"""
|
||||
# Execute synchronous callback if registered
|
||||
if display_type in sync_display_callbacks:
|
||||
callback = sync_display_callbacks[display_type]
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, lambda: callback(**kwargs))
|
||||
|
||||
# Execute asynchronous callback if registered
|
||||
if display_type in async_display_callbacks:
|
||||
callback = async_display_callbacks[display_type]
|
||||
await callback(**kwargs)
|
||||
|
||||
def _clean_display_content(content: str, max_length: int = 20000) -> str:
|
||||
"""Helper function to clean and truncate content for display."""
|
||||
if not content or not str(content).strip():
|
||||
return ""
|
||||
|
||||
content = str(content)
|
||||
# Handle base64 content
|
||||
if "base64" in content:
|
||||
content_parts = []
|
||||
for line in content.split('\n'):
|
||||
if "base64" not in line:
|
||||
content_parts.append(line)
|
||||
content = '\n'.join(content_parts)
|
||||
|
||||
# Truncate if too long
|
||||
if len(content) > max_length:
|
||||
content = content[:max_length] + "..."
|
||||
|
||||
return content.strip()
|
||||
|
||||
def display_interaction(message, response, markdown=True, generation_time=None, console=None):
|
||||
"""Synchronous version of display_interaction."""
|
||||
if console is None:
|
||||
console = Console()
|
||||
|
||||
if isinstance(message, list):
|
||||
text_content = next((item["text"] for item in message if item["type"] == "text"), "")
|
||||
message = text_content
|
||||
|
||||
message = _clean_display_content(str(message))
|
||||
response = _clean_display_content(str(response))
|
||||
|
||||
# Execute synchronous callback if registered
|
||||
if 'interaction' in sync_display_callbacks:
|
||||
sync_display_callbacks['interaction'](
|
||||
message=message,
|
||||
response=response,
|
||||
markdown=markdown,
|
||||
generation_time=generation_time
|
||||
)
|
||||
|
||||
# Rest of the display logic...
|
||||
if generation_time:
|
||||
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
|
||||
|
||||
if markdown:
|
||||
console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
|
||||
else:
|
||||
console.print(Panel.fit(Text(message, style="bold green"), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Text(response, style="bold white"), title="Response", border_style="cyan"))
|
||||
console.print(Panel.fit(Text(response, style="bold blue"), title="Response", border_style="cyan"))
|
||||
|
||||
def display_self_reflection(message: str):
|
||||
console = Console()
|
||||
def display_self_reflection(message: str, console=None):
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'self_reflection' in sync_display_callbacks:
|
||||
sync_display_callbacks['self_reflection'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
|
||||
|
||||
def display_instruction(message: str):
|
||||
console = Console()
|
||||
def display_instruction(message: str, console=None):
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'instruction' in sync_display_callbacks:
|
||||
sync_display_callbacks['instruction'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
|
||||
|
||||
def display_tool_call(message: str):
|
||||
console = Console()
|
||||
def display_tool_call(message: str, console=None):
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'tool_call' in sync_display_callbacks:
|
||||
sync_display_callbacks['tool_call'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
|
||||
|
||||
def display_error(message: str):
|
||||
console = Console()
|
||||
def display_error(message: str, console=None):
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'error' in sync_display_callbacks:
|
||||
sync_display_callbacks['error'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
|
||||
# Store errors
|
||||
error_logs.append(message)
|
||||
|
||||
def display_generating(content: str = "", start_time: Optional[float] = None):
|
||||
if not content or not str(content).strip():
|
||||
return Panel("", title="", border_style="green")
|
||||
|
||||
elapsed_str = ""
|
||||
if start_time is not None:
|
||||
elapsed = time.time() - start_time
|
||||
elapsed_str = f" {elapsed:.1f}s"
|
||||
|
||||
content = _clean_display_content(str(content))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'generating' in sync_display_callbacks:
|
||||
sync_display_callbacks['generating'](
|
||||
content=content,
|
||||
elapsed_time=elapsed_str.strip() if elapsed_str else None
|
||||
)
|
||||
|
||||
return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
|
||||
|
||||
# Async versions with 'a' prefix
|
||||
async def adisplay_interaction(message, response, markdown=True, generation_time=None, console=None):
|
||||
"""Async version of display_interaction."""
|
||||
if console is None:
|
||||
console = Console()
|
||||
|
||||
if isinstance(message, list):
|
||||
text_content = next((item["text"] for item in message if item["type"] == "text"), "")
|
||||
message = text_content
|
||||
|
||||
message = _clean_display_content(str(message))
|
||||
response = _clean_display_content(str(response))
|
||||
|
||||
# Execute callbacks
|
||||
await execute_callback(
|
||||
'interaction',
|
||||
message=message,
|
||||
response=response,
|
||||
markdown=markdown,
|
||||
generation_time=generation_time
|
||||
)
|
||||
|
||||
# Rest of the display logic...
|
||||
if generation_time:
|
||||
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
|
||||
|
||||
if markdown:
|
||||
console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
|
||||
else:
|
||||
console.print(Panel.fit(Text(message, style="bold green"), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Text(response, style="bold blue"), title="Response", border_style="cyan"))
|
||||
|
||||
async def adisplay_self_reflection(message: str, console=None):
|
||||
"""Async version of display_self_reflection."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'self_reflection' in async_display_callbacks:
|
||||
await async_display_callbacks['self_reflection'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
|
||||
|
||||
async def adisplay_instruction(message: str, console=None):
|
||||
"""Async version of display_instruction."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'instruction' in async_display_callbacks:
|
||||
await async_display_callbacks['instruction'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
|
||||
|
||||
async def adisplay_tool_call(message: str, console=None):
|
||||
"""Async version of display_tool_call."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'tool_call' in async_display_callbacks:
|
||||
await async_display_callbacks['tool_call'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
|
||||
|
||||
async def adisplay_error(message: str, console=None):
|
||||
"""Async version of display_error."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'error' in async_display_callbacks:
|
||||
await async_display_callbacks['error'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
|
||||
error_logs.append(message)
|
||||
|
||||
async def adisplay_generating(content: str = "", start_time: Optional[float] = None):
|
||||
"""Async version of display_generating."""
|
||||
if not content or not str(content).strip():
|
||||
return Panel("", title="", border_style="green")
|
||||
|
||||
elapsed_str = ""
|
||||
if start_time is not None:
|
||||
elapsed = time.time() - start_time
|
||||
elapsed_str = f" {elapsed:.1f}s"
|
||||
|
||||
content = _clean_display_content(str(content))
|
||||
|
||||
if 'generating' in async_display_callbacks:
|
||||
await async_display_callbacks['generating'](
|
||||
content=content,
|
||||
elapsed_time=elapsed_str.strip() if elapsed_str else None
|
||||
)
|
||||
|
||||
return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
|
||||
|
||||
def clean_triple_backticks(text: str) -> str:
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from .process import Process
|
||||
|
||||
__all__ = ['Process']
|
||||
@@ -0,0 +1,534 @@
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Optional, List, Any, AsyncGenerator
|
||||
from pydantic import BaseModel
|
||||
from ..agent.agent import Agent
|
||||
from ..task.task import Task
|
||||
from ..main import display_error, client
|
||||
|
||||
class LoopItems(BaseModel):
|
||||
items: List[Any]
|
||||
|
||||
class Process:
|
||||
def __init__(self, tasks: Dict[str, Task], agents: List[Agent], manager_llm: Optional[str] = None, verbose: bool = False):
|
||||
self.tasks = tasks
|
||||
self.agents = agents
|
||||
self.manager_llm = manager_llm
|
||||
self.verbose = verbose
|
||||
|
||||
async def aworkflow(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of workflow method"""
|
||||
# Build workflow relationships first
|
||||
for task in self.tasks.values():
|
||||
if task.next_tasks:
|
||||
for next_task_name in task.next_tasks:
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
if next_task:
|
||||
next_task.previous_tasks.append(task.name)
|
||||
|
||||
# Find start task
|
||||
start_task = None
|
||||
for task_id, task in self.tasks.items():
|
||||
if task.is_start:
|
||||
start_task = task
|
||||
break
|
||||
|
||||
if not start_task:
|
||||
start_task = list(self.tasks.values())[0]
|
||||
logging.info("No start task marked, using first task")
|
||||
|
||||
current_task = start_task
|
||||
visited_tasks = set()
|
||||
loop_data = {} # Store loop-specific data
|
||||
|
||||
while current_task and current_task.id not in visited_tasks:
|
||||
task_id = current_task.id
|
||||
logging.info(f"Executing workflow task: {current_task.name if current_task.name else task_id}")
|
||||
|
||||
# Add context from previous tasks to description
|
||||
if current_task.previous_tasks or current_task.context:
|
||||
context = "\nInput data from previous tasks:"
|
||||
|
||||
# Add data from previous tasks in workflow
|
||||
for prev_name in current_task.previous_tasks:
|
||||
prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
|
||||
if prev_task and prev_task.result:
|
||||
# Handle loop data
|
||||
if current_task.task_type == "loop":
|
||||
# create a loop manager Agent
|
||||
loop_manager = Agent(
|
||||
name="Loop Manager",
|
||||
role="Loop data processor",
|
||||
goal="Process loop data and convert it to list format",
|
||||
backstory="Expert at handling loop data and converting it to proper format",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# get the loop data convert it to list using calling Agent class chat
|
||||
loop_prompt = f"""
|
||||
Process this data into a list format:
|
||||
{prev_task.result.raw}
|
||||
|
||||
Return a JSON object with an 'items' array containing the items to process.
|
||||
"""
|
||||
if current_task.async_execution:
|
||||
loop_data_str = await loop_manager.achat(
|
||||
prompt=loop_prompt,
|
||||
output_json=LoopItems
|
||||
)
|
||||
else:
|
||||
loop_data_str = loop_manager.chat(
|
||||
prompt=loop_prompt,
|
||||
output_json=LoopItems
|
||||
)
|
||||
|
||||
try:
|
||||
# The response will already be parsed into LoopItems model
|
||||
loop_data[f"loop_{current_task.name}"] = {
|
||||
"items": loop_data_str.items,
|
||||
"index": 0,
|
||||
"remaining": len(loop_data_str.items)
|
||||
}
|
||||
context += f"\nCurrent loop item: {loop_data_str.items[0]}"
|
||||
except Exception as e:
|
||||
display_error(f"Failed to process loop data: {e}")
|
||||
context += f"\n{prev_name}: {prev_task.result.raw}"
|
||||
else:
|
||||
context += f"\n{prev_name}: {prev_task.result.raw}"
|
||||
|
||||
# Add data from context tasks
|
||||
if current_task.context:
|
||||
for ctx_task in current_task.context:
|
||||
if ctx_task.result and ctx_task.name != current_task.name:
|
||||
context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
|
||||
|
||||
# Update task description with context
|
||||
current_task.description = current_task.description + context
|
||||
|
||||
# Execute task using existing run_task method
|
||||
yield task_id
|
||||
visited_tasks.add(task_id)
|
||||
|
||||
# Handle loop progression
|
||||
if current_task.task_type == "loop":
|
||||
loop_key = f"loop_{current_task.name}"
|
||||
if loop_key in loop_data:
|
||||
loop_info = loop_data[loop_key]
|
||||
loop_info["index"] += 1
|
||||
has_more = loop_info["remaining"] > 0
|
||||
|
||||
# Update result to trigger correct condition
|
||||
if current_task.result:
|
||||
result = current_task.result.raw
|
||||
if has_more:
|
||||
result += "\nmore"
|
||||
else:
|
||||
result += "\ndone"
|
||||
current_task.result.raw = result
|
||||
|
||||
# Determine next task based on result
|
||||
next_task = None
|
||||
if current_task.result:
|
||||
if current_task.task_type in ["decision", "loop"]:
|
||||
result = current_task.result.raw.lower()
|
||||
# Check conditions
|
||||
for condition, tasks in current_task.condition.items():
|
||||
if condition.lower() in result and tasks:
|
||||
next_task_name = tasks[0]
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
# For loops, allow revisiting the same task
|
||||
if next_task and next_task.id == current_task.id:
|
||||
visited_tasks.discard(current_task.id)
|
||||
break
|
||||
|
||||
if not next_task and current_task.next_tasks:
|
||||
next_task_name = current_task.next_tasks[0]
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
|
||||
current_task = next_task
|
||||
if not current_task:
|
||||
logging.info("Workflow execution completed")
|
||||
break
|
||||
|
||||
async def asequential(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of sequential method"""
|
||||
for task_id in self.tasks:
|
||||
if self.tasks[task_id].status != "completed":
|
||||
yield task_id
|
||||
|
||||
async def ahierarchical(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of hierarchical method"""
|
||||
logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
|
||||
manager_agent = Agent(
|
||||
name="Manager",
|
||||
role="Project manager",
|
||||
goal="Manage the entire flow of tasks and delegate them to the right agent",
|
||||
backstory="Expert project manager to coordinate tasks among agents",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True,
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
class ManagerInstructions(BaseModel):
|
||||
task_id: int
|
||||
agent_name: str
|
||||
action: str
|
||||
|
||||
manager_task = Task(
|
||||
name="manager_task",
|
||||
description="Decide the order of tasks and which agent executes them",
|
||||
expected_output="All tasks completed successfully",
|
||||
agent=manager_agent
|
||||
)
|
||||
manager_task_id = yield manager_task
|
||||
logging.info(f"Created manager task with ID {manager_task_id}")
|
||||
|
||||
completed_count = 0
|
||||
total_tasks = len(self.tasks) - 1
|
||||
logging.info(f"Need to complete {total_tasks} tasks (excluding manager task)")
|
||||
|
||||
while completed_count < total_tasks:
|
||||
tasks_summary = []
|
||||
for tid, tk in self.tasks.items():
|
||||
if tk.name == "manager_task":
|
||||
continue
|
||||
task_info = {
|
||||
"task_id": tid,
|
||||
"name": tk.name,
|
||||
"description": tk.description,
|
||||
"status": tk.status if tk.status else "not started",
|
||||
"agent": tk.agent.name if tk.agent else "No agent"
|
||||
}
|
||||
tasks_summary.append(task_info)
|
||||
logging.info(f"Task {tid} status: {task_info}")
|
||||
|
||||
manager_prompt = f"""
|
||||
Here is the current status of all tasks except yours (manager_task):
|
||||
{tasks_summary}
|
||||
|
||||
Provide a JSON with the structure:
|
||||
{{
|
||||
"task_id": <int>,
|
||||
"agent_name": "<string>",
|
||||
"action": "<execute or stop>"
|
||||
}}
|
||||
"""
|
||||
|
||||
try:
|
||||
logging.info("Requesting manager instructions...")
|
||||
if manager_task.async_execution:
|
||||
manager_response = await client.beta.chat.completions.parse(
|
||||
model=self.manager_llm,
|
||||
messages=[
|
||||
{"role": "system", "content": manager_task.description},
|
||||
{"role": "user", "content": manager_prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format=ManagerInstructions
|
||||
)
|
||||
else:
|
||||
manager_response = client.beta.chat.completions.parse(
|
||||
model=self.manager_llm,
|
||||
messages=[
|
||||
{"role": "system", "content": manager_task.description},
|
||||
{"role": "user", "content": manager_prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format=ManagerInstructions
|
||||
)
|
||||
parsed_instructions = manager_response.choices[0].message.parsed
|
||||
logging.info(f"Manager instructions: {parsed_instructions}")
|
||||
except Exception as e:
|
||||
display_error(f"Manager parse error: {e}")
|
||||
logging.error(f"Manager parse error: {str(e)}", exc_info=True)
|
||||
break
|
||||
|
||||
selected_task_id = parsed_instructions.task_id
|
||||
selected_agent_name = parsed_instructions.agent_name
|
||||
action = parsed_instructions.action
|
||||
|
||||
logging.info(f"Manager selected task_id={selected_task_id}, agent={selected_agent_name}, action={action}")
|
||||
|
||||
if action.lower() == "stop":
|
||||
logging.info("Manager decided to stop task execution")
|
||||
break
|
||||
|
||||
if selected_task_id not in self.tasks:
|
||||
error_msg = f"Manager selected invalid task id {selected_task_id}"
|
||||
display_error(error_msg)
|
||||
logging.error(error_msg)
|
||||
break
|
||||
|
||||
original_agent = self.tasks[selected_task_id].agent.name if self.tasks[selected_task_id].agent else "None"
|
||||
for a in self.agents:
|
||||
if a.name == selected_agent_name:
|
||||
self.tasks[selected_task_id].agent = a
|
||||
logging.info(f"Changed agent for task {selected_task_id} from {original_agent} to {selected_agent_name}")
|
||||
break
|
||||
|
||||
if self.tasks[selected_task_id].status != "completed":
|
||||
logging.info(f"Starting execution of task {selected_task_id}")
|
||||
yield selected_task_id
|
||||
logging.info(f"Finished execution of task {selected_task_id}, status: {self.tasks[selected_task_id].status}")
|
||||
|
||||
if self.tasks[selected_task_id].status == "completed":
|
||||
completed_count += 1
|
||||
logging.info(f"Task {selected_task_id} completed. Total completed: {completed_count}/{total_tasks}")
|
||||
|
||||
self.tasks[manager_task.id].status = "completed"
|
||||
if self.verbose >= 1:
|
||||
logging.info("All tasks completed under manager supervision.")
|
||||
logging.info("Hierarchical task execution finished")
|
||||
|
||||
def workflow(self):
|
||||
"""Synchronous version of workflow method"""
|
||||
# Build workflow relationships first
|
||||
for task in self.tasks.values():
|
||||
if task.next_tasks:
|
||||
for next_task_name in task.next_tasks:
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
if next_task:
|
||||
next_task.previous_tasks.append(task.name)
|
||||
|
||||
# Find start task
|
||||
start_task = None
|
||||
for task_id, task in self.tasks.items():
|
||||
if task.is_start:
|
||||
start_task = task
|
||||
break
|
||||
|
||||
if not start_task:
|
||||
start_task = list(self.tasks.values())[0]
|
||||
logging.info("No start task marked, using first task")
|
||||
|
||||
current_task = start_task
|
||||
visited_tasks = set()
|
||||
loop_data = {} # Store loop-specific data
|
||||
|
||||
while current_task and current_task.id not in visited_tasks:
|
||||
task_id = current_task.id
|
||||
logging.info(f"Executing workflow task: {current_task.name if current_task.name else task_id}")
|
||||
|
||||
# Add context from previous tasks to description
|
||||
if current_task.previous_tasks or current_task.context:
|
||||
context = "\nInput data from previous tasks:"
|
||||
|
||||
# Add data from previous tasks in workflow
|
||||
for prev_name in current_task.previous_tasks:
|
||||
prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
|
||||
if prev_task and prev_task.result:
|
||||
# Handle loop data
|
||||
if current_task.task_type == "loop":
|
||||
# create a loop manager Agent
|
||||
loop_manager = Agent(
|
||||
name="Loop Manager",
|
||||
role="Loop data processor",
|
||||
goal="Process loop data and convert it to list format",
|
||||
backstory="Expert at handling loop data and converting it to proper format",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# get the loop data convert it to list using calling Agent class chat
|
||||
loop_prompt = f"""
|
||||
Process this data into a list format:
|
||||
{prev_task.result.raw}
|
||||
|
||||
Return a JSON object with an 'items' array containing the items to process.
|
||||
"""
|
||||
loop_data_str = loop_manager.chat(
|
||||
prompt=loop_prompt,
|
||||
output_json=LoopItems
|
||||
)
|
||||
|
||||
try:
|
||||
# The response will already be parsed into LoopItems model
|
||||
loop_data[f"loop_{current_task.name}"] = {
|
||||
"items": loop_data_str.items,
|
||||
"index": 0,
|
||||
"remaining": len(loop_data_str.items)
|
||||
}
|
||||
context += f"\nCurrent loop item: {loop_data_str.items[0]}"
|
||||
except Exception as e:
|
||||
display_error(f"Failed to process loop data: {e}")
|
||||
context += f"\n{prev_name}: {prev_task.result.raw}"
|
||||
else:
|
||||
context += f"\n{prev_name}: {prev_task.result.raw}"
|
||||
|
||||
# Add data from context tasks
|
||||
if current_task.context:
|
||||
for ctx_task in current_task.context:
|
||||
if ctx_task.result and ctx_task.name != current_task.name:
|
||||
context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
|
||||
|
||||
# Update task description with context
|
||||
current_task.description = current_task.description + context
|
||||
|
||||
# Execute task using existing run_task method
|
||||
yield task_id
|
||||
visited_tasks.add(task_id)
|
||||
|
||||
# Handle loop progression
|
||||
if current_task.task_type == "loop":
|
||||
loop_key = f"loop_{current_task.name}"
|
||||
if loop_key in loop_data:
|
||||
loop_info = loop_data[loop_key]
|
||||
loop_info["index"] += 1
|
||||
has_more = loop_info["remaining"] > 0
|
||||
|
||||
# Update result to trigger correct condition
|
||||
if current_task.result:
|
||||
result = current_task.result.raw
|
||||
if has_more:
|
||||
result += "\nmore"
|
||||
else:
|
||||
result += "\ndone"
|
||||
current_task.result.raw = result
|
||||
|
||||
# Determine next task based on result
|
||||
next_task = None
|
||||
if current_task.result:
|
||||
if current_task.task_type in ["decision", "loop"]:
|
||||
result = current_task.result.raw.lower()
|
||||
# Check conditions
|
||||
for condition, tasks in current_task.condition.items():
|
||||
if condition.lower() in result and tasks:
|
||||
next_task_name = tasks[0]
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
# For loops, allow revisiting the same task
|
||||
if next_task and next_task.id == current_task.id:
|
||||
visited_tasks.discard(current_task.id)
|
||||
break
|
||||
|
||||
if not next_task and current_task.next_tasks:
|
||||
next_task_name = current_task.next_tasks[0]
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
|
||||
current_task = next_task
|
||||
if not current_task:
|
||||
logging.info("Workflow execution completed")
|
||||
break
|
||||
|
||||
def sequential(self):
|
||||
"""Synchronous version of sequential method"""
|
||||
for task_id in self.tasks:
|
||||
if self.tasks[task_id].status != "completed":
|
||||
yield task_id
|
||||
|
||||
def hierarchical(self):
|
||||
"""Synchronous version of hierarchical method"""
|
||||
logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
|
||||
manager_agent = Agent(
|
||||
name="Manager",
|
||||
role="Project manager",
|
||||
goal="Manage the entire flow of tasks and delegate them to the right agent",
|
||||
backstory="Expert project manager to coordinate tasks among agents",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True,
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
class ManagerInstructions(BaseModel):
|
||||
task_id: int
|
||||
agent_name: str
|
||||
action: str
|
||||
|
||||
manager_task = Task(
|
||||
name="manager_task",
|
||||
description="Decide the order of tasks and which agent executes them",
|
||||
expected_output="All tasks completed successfully",
|
||||
agent=manager_agent
|
||||
)
|
||||
manager_task_id = yield manager_task
|
||||
logging.info(f"Created manager task with ID {manager_task_id}")
|
||||
|
||||
completed_count = 0
|
||||
total_tasks = len(self.tasks) - 1
|
||||
logging.info(f"Need to complete {total_tasks} tasks (excluding manager task)")
|
||||
|
||||
while completed_count < total_tasks:
|
||||
tasks_summary = []
|
||||
for tid, tk in self.tasks.items():
|
||||
if tk.name == "manager_task":
|
||||
continue
|
||||
task_info = {
|
||||
"task_id": tid,
|
||||
"name": tk.name,
|
||||
"description": tk.description,
|
||||
"status": tk.status if tk.status else "not started",
|
||||
"agent": tk.agent.name if tk.agent else "No agent"
|
||||
}
|
||||
tasks_summary.append(task_info)
|
||||
logging.info(f"Task {tid} status: {task_info}")
|
||||
|
||||
manager_prompt = f"""
|
||||
Here is the current status of all tasks except yours (manager_task):
|
||||
{tasks_summary}
|
||||
|
||||
Provide a JSON with the structure:
|
||||
{{
|
||||
"task_id": <int>,
|
||||
"agent_name": "<string>",
|
||||
"action": "<execute or stop>"
|
||||
}}
|
||||
"""
|
||||
|
||||
try:
|
||||
logging.info("Requesting manager instructions...")
|
||||
manager_response = client.beta.chat.completions.parse(
|
||||
model=self.manager_llm,
|
||||
messages=[
|
||||
{"role": "system", "content": manager_task.description},
|
||||
{"role": "user", "content": manager_prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format=ManagerInstructions
|
||||
)
|
||||
parsed_instructions = manager_response.choices[0].message.parsed
|
||||
logging.info(f"Manager instructions: {parsed_instructions}")
|
||||
except Exception as e:
|
||||
display_error(f"Manager parse error: {e}")
|
||||
logging.error(f"Manager parse error: {str(e)}", exc_info=True)
|
||||
break
|
||||
|
||||
selected_task_id = parsed_instructions.task_id
|
||||
selected_agent_name = parsed_instructions.agent_name
|
||||
action = parsed_instructions.action
|
||||
|
||||
logging.info(f"Manager selected task_id={selected_task_id}, agent={selected_agent_name}, action={action}")
|
||||
|
||||
if action.lower() == "stop":
|
||||
logging.info("Manager decided to stop task execution")
|
||||
break
|
||||
|
||||
if selected_task_id not in self.tasks:
|
||||
error_msg = f"Manager selected invalid task id {selected_task_id}"
|
||||
display_error(error_msg)
|
||||
logging.error(error_msg)
|
||||
break
|
||||
|
||||
original_agent = self.tasks[selected_task_id].agent.name if self.tasks[selected_task_id].agent else "None"
|
||||
for a in self.agents:
|
||||
if a.name == selected_agent_name:
|
||||
self.tasks[selected_task_id].agent = a
|
||||
logging.info(f"Changed agent for task {selected_task_id} from {original_agent} to {selected_agent_name}")
|
||||
break
|
||||
|
||||
if self.tasks[selected_task_id].status != "completed":
|
||||
logging.info(f"Starting execution of task {selected_task_id}")
|
||||
yield selected_task_id
|
||||
logging.info(f"Finished execution of task {selected_task_id}, status: {self.tasks[selected_task_id].status}")
|
||||
|
||||
if self.tasks[selected_task_id].status == "completed":
|
||||
completed_count += 1
|
||||
logging.info(f"Task {selected_task_id} completed. Total completed: {completed_count}/{total_tasks}")
|
||||
|
||||
self.tasks[manager_task.id].status = "completed"
|
||||
if self.verbose >= 1:
|
||||
logging.info("All tasks completed under manager supervision.")
|
||||
logging.info("Hierarchical task execution finished")
|
||||
@@ -1,8 +1,10 @@
|
||||
import logging
|
||||
from typing import List, Optional, Dict, Any, Type
|
||||
import asyncio
|
||||
from typing import List, Optional, Dict, Any, Type, Callable, Union, Coroutine
|
||||
from pydantic import BaseModel
|
||||
from ..main import TaskOutput
|
||||
from ..agent.agent import Agent
|
||||
import uuid
|
||||
|
||||
class Task:
|
||||
def __init__(
|
||||
@@ -18,15 +20,22 @@ class Task:
|
||||
output_file: Optional[str] = None,
|
||||
output_json: Optional[Type[BaseModel]] = None,
|
||||
output_pydantic: Optional[Type[BaseModel]] = None,
|
||||
callback: Optional[Any] = None,
|
||||
callback: Optional[Union[Callable[[TaskOutput], Any], Callable[[TaskOutput], Coroutine[Any, Any, Any]]]] = None,
|
||||
status: str = "not started",
|
||||
result: Optional[TaskOutput] = None,
|
||||
create_directory: Optional[bool] = False,
|
||||
id: Optional[int] = None
|
||||
id: Optional[int] = None,
|
||||
images: Optional[List[str]] = None,
|
||||
next_tasks: Optional[List[str]] = None,
|
||||
task_type: str = "task",
|
||||
condition: Optional[Dict[str, List[str]]] = None,
|
||||
is_start: bool = False,
|
||||
loop_state: Optional[Dict[str, Union[str, int]]] = None
|
||||
):
|
||||
self.id = str(uuid.uuid4()) if id is None else str(id)
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.expected_output = expected_output
|
||||
self.name = name
|
||||
self.agent = agent
|
||||
self.tools = tools if tools else []
|
||||
self.context = context if context else []
|
||||
@@ -39,10 +48,27 @@ class Task:
|
||||
self.status = status
|
||||
self.result = result
|
||||
self.create_directory = create_directory
|
||||
self.id = id
|
||||
self.images = images if images else []
|
||||
self.next_tasks = next_tasks if next_tasks else []
|
||||
self.task_type = task_type
|
||||
self.condition = condition if condition else {}
|
||||
self.is_start = is_start
|
||||
self.loop_state = loop_state if loop_state else {}
|
||||
|
||||
if self.output_json and self.output_pydantic:
|
||||
raise ValueError("Only one output type can be defined")
|
||||
|
||||
# Track previous tasks based on next_tasks relationships
|
||||
self.previous_tasks = []
|
||||
|
||||
def __str__(self):
|
||||
return f"Task(name='{self.name if self.name else 'None'}', description='{self.description}', agent='{self.agent.name if self.agent else 'None'}', status='{self.status}')"
|
||||
return f"Task(name='{self.name if self.name else 'None'}', description='{self.description}', agent='{self.agent.name if self.agent else 'None'}', status='{self.status}')"
|
||||
|
||||
async def execute_callback(self, task_output: TaskOutput) -> None:
|
||||
"""Execute the callback function, handling both sync and async callbacks"""
|
||||
if self.callback:
|
||||
if asyncio.iscoroutinefunction(self.callback):
|
||||
await self.callback(task_output)
|
||||
else:
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, self.callback, task_output)
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.6"
|
||||
version = "0.0.20"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
authors = [
|
||||
{ name="Mervin Praison" }
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
from typing import List, Dict
|
||||
from pydantic import BaseModel
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.main import TaskOutput
|
||||
|
||||
# Pydantic models for structured output
|
||||
class Chapter(BaseModel):
|
||||
chapter_number: int
|
||||
title: str
|
||||
outline: str
|
||||
|
||||
class StoryOutline(BaseModel):
|
||||
title: str
|
||||
total_chapters: int
|
||||
chapters: List[Chapter]
|
||||
|
||||
class ChapterContent(BaseModel):
|
||||
chapter_number: int
|
||||
title: str
|
||||
content: str
|
||||
|
||||
# Create the story planner agent
|
||||
planner_agent = Agent(
|
||||
name="Story Planner",
|
||||
role="Creative Writing Architect",
|
||||
goal="Create detailed story outlines with chapter breakdowns",
|
||||
backstory="Expert storyteller skilled in narrative structure and plot development",
|
||||
verbose=True,
|
||||
llm="gpt-4o-mini",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create the writer agent
|
||||
writer_agent = Agent(
|
||||
name="Story Writer",
|
||||
role="Creative Writer",
|
||||
goal="Write engaging and cohesive story chapters",
|
||||
backstory="Experienced writer skilled in bringing stories to life with vivid details and engaging narrative",
|
||||
verbose=True,
|
||||
llm="gpt-4o-mini",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Story title
|
||||
story_title = "The Curious Cat"
|
||||
|
||||
# Step 1: Create outline task
|
||||
outline_task = Task(
|
||||
name="story_outline",
|
||||
description=f"""Create a detailed story outline for a story titled '{story_title}'.
|
||||
The outline should include:
|
||||
1. A compelling story arc
|
||||
2. Clear chapter breakdown
|
||||
3. Brief description of what happens in each chapter
|
||||
4. Character introductions and development points
|
||||
|
||||
Provide the response in this exact JSON format:
|
||||
{{
|
||||
"title": "Story title",
|
||||
"total_chapters": number,
|
||||
"chapters": [
|
||||
{{
|
||||
"chapter_number": 1,
|
||||
"title": "Chapter title",
|
||||
"outline": "Detailed chapter outline"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
""",
|
||||
expected_output="Complete story outline",
|
||||
agent=planner_agent,
|
||||
output_pydantic=StoryOutline
|
||||
)
|
||||
|
||||
# Create initial workflow for outline
|
||||
outline_workflow = PraisonAIAgents(
|
||||
agents=[planner_agent],
|
||||
tasks=[outline_task],
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Get the outline
|
||||
outline_result = outline_workflow.start()
|
||||
story_outline = outline_result["task_results"][0].pydantic
|
||||
|
||||
# Step 2: Create tasks for each chapter
|
||||
chapter_tasks = []
|
||||
chapters_content = []
|
||||
|
||||
# Create a task for each chapter
|
||||
for chapter in story_outline.chapters:
|
||||
chapter_task = Task(
|
||||
name=f"write_chapter_{chapter.chapter_number}",
|
||||
description=f"""Write chapter {chapter.chapter_number}: {chapter.title}
|
||||
Chapter outline: {chapter.outline}
|
||||
|
||||
Write a complete, engaging chapter following this outline.
|
||||
Return in this exact JSON format:
|
||||
{{
|
||||
"chapter_number": {chapter.chapter_number},
|
||||
"title": "{chapter.title}",
|
||||
"content": "The full chapter content..."
|
||||
}}
|
||||
""",
|
||||
expected_output="Complete chapter content",
|
||||
agent=writer_agent,
|
||||
output_pydantic=ChapterContent,
|
||||
context=[outline_task]
|
||||
)
|
||||
chapter_tasks.append(chapter_task)
|
||||
|
||||
# Create sequential workflow for chapters
|
||||
chapter_workflow = PraisonAIAgents(
|
||||
agents=[writer_agent],
|
||||
tasks=chapter_tasks,
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Run the chapter workflow
|
||||
chapter_results = chapter_workflow.start()
|
||||
|
||||
# Collect and validate all chapter contents
|
||||
for task_result in chapter_results["task_results"].values():
|
||||
if task_result and task_result.pydantic:
|
||||
chapters_content.append(task_result.pydantic)
|
||||
|
||||
# Sort chapters by chapter number
|
||||
chapters_content.sort(key=lambda x: x.chapter_number)
|
||||
|
||||
# Format final result
|
||||
story = {
|
||||
"title": story_outline.title,
|
||||
"outline": story_outline.model_dump(),
|
||||
"chapters": [chapter.model_dump() for chapter in chapters_content]
|
||||
}
|
||||
|
||||
# Print results
|
||||
print("\n=== Story Generation Results ===")
|
||||
print(f"\nTitle: {story['title']}")
|
||||
print("\nOutline:")
|
||||
print(story['outline'])
|
||||
print("\nChapters:")
|
||||
for chapter in story['chapters']:
|
||||
print(f"\nChapter {chapter['chapter_number']}: {chapter['title']}")
|
||||
print(chapter['content'][:200] + "...") # Print first 200 chars of each chapter
|
||||
Generated
+1
-1
@@ -186,7 +186,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.6"
|
||||
version = "0.0.20"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from typing import List, Dict
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
# 1. Tool
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles, URLs, and snippets.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
# 2. Agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 3. Tasks
|
||||
collect_task = Task(
|
||||
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
|
||||
expected_output="List of search results with titles, URLs, and snippets.",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
is_start=True,
|
||||
next_tasks=["validate_data"]
|
||||
)
|
||||
|
||||
validate_task = Task(
|
||||
description="""Validate the collected data. Check if:
|
||||
1. At least 5 results are returned.
|
||||
2. Each result contains a title and a URL.
|
||||
Return validation_result as 'valid' or 'invalid' only no other text.""",
|
||||
expected_output="Validation result indicating if data is valid or invalid.",
|
||||
agent=data_agent,
|
||||
name="validate_data",
|
||||
task_type="decision",
|
||||
condition={
|
||||
"valid": [], # End the workflow on valid data
|
||||
"invalid": ["collect_data"] # Retry data collection on invalid data
|
||||
},
|
||||
)
|
||||
|
||||
# 4. AI Agents Workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[collect_task, validate_task],
|
||||
verbose=1,
|
||||
process="workflow"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
@@ -0,0 +1,253 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import random
|
||||
from typing import List, Dict, Union
|
||||
import json
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Add Pydantic models for data validation
|
||||
class Person(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
job: str
|
||||
city: str
|
||||
salary: int
|
||||
|
||||
class ProcessedPerson(Person):
|
||||
salary_category: str
|
||||
age_group: str
|
||||
processing_status: str
|
||||
|
||||
class DataList(BaseModel):
|
||||
items: List[Dict]
|
||||
|
||||
class ValidationResult(BaseModel):
|
||||
validation_result: str
|
||||
details: str = ""
|
||||
|
||||
def random_data_of_individuals() -> List[Dict]:
|
||||
"""Generate random individual data"""
|
||||
names = ["John", "Jane", "Mike", "Sarah", "David", "Emma"]
|
||||
jobs = ["Engineer", "Doctor", "Teacher", "Artist", "Developer"]
|
||||
cities = ["New York", "London", "Tokyo", "Paris", "Berlin"]
|
||||
|
||||
data = []
|
||||
for _ in range(random.randint(3, 7)):
|
||||
person = {
|
||||
"name": random.choice(names),
|
||||
"age": random.randint(25, 65),
|
||||
"job": random.choice(jobs),
|
||||
"city": random.choice(cities),
|
||||
"salary": random.randint(30000, 120000)
|
||||
}
|
||||
data.append(person)
|
||||
return data
|
||||
|
||||
def process_data_of_individuals(data: Union[List[Dict], Dict, str]) -> Dict:
|
||||
"""Process individual data by adding categories and analysis"""
|
||||
try:
|
||||
print("\n[DEBUG] process_data_of_individuals input:", data)
|
||||
print("[DEBUG] Current workflow state:")
|
||||
print("- total_records:", workflow.get_state("total_records"))
|
||||
print("- current_index:", workflow.get_state("current_index"))
|
||||
print("- remaining:", workflow.get_state("remaining"))
|
||||
|
||||
# Get the items list from the collect_task result
|
||||
collect_result = None
|
||||
for task in workflow.tasks.values():
|
||||
if task.name == "collect_data" and task.result:
|
||||
try:
|
||||
collect_data = json.loads(task.result.raw)
|
||||
collect_result = collect_data.get("items", [])
|
||||
print("[DEBUG] Found collect_data items:", len(collect_result))
|
||||
except:
|
||||
print("[DEBUG] Failed to parse collect_data result")
|
||||
|
||||
# Handle string input by trying to parse it as JSON
|
||||
if isinstance(data, str):
|
||||
if ":" in data and not data.strip().startswith("{"):
|
||||
# Convert string format to dictionary
|
||||
pairs = [pair.strip() for pair in data.split(",")]
|
||||
data_dict = {}
|
||||
for pair in pairs:
|
||||
key, value = pair.split(":")
|
||||
key = key.strip().lower()
|
||||
value = value.strip()
|
||||
if key == "age" or key == "salary":
|
||||
value = int(value)
|
||||
data_dict[key] = value
|
||||
data = data_dict
|
||||
else:
|
||||
data = json.loads(data)
|
||||
print("[DEBUG] Parsed data:", data)
|
||||
|
||||
# Handle single record
|
||||
if isinstance(data, dict):
|
||||
person = data
|
||||
# Initialize total records if not set
|
||||
total_records = workflow.get_state("total_records")
|
||||
if total_records is None and collect_result:
|
||||
total_records = len(collect_result)
|
||||
workflow.set_state("total_records", total_records)
|
||||
print(f"[DEBUG] Initialized total_records to {total_records}")
|
||||
|
||||
current_index = workflow.get_state("current_index", 0)
|
||||
total_records = total_records or 1
|
||||
remaining = total_records - (current_index + 1)
|
||||
workflow.set_state("remaining", remaining)
|
||||
print(f"[DEBUG] Processing record {current_index + 1}/{total_records}")
|
||||
|
||||
elif isinstance(data, list):
|
||||
if len(data) == 0:
|
||||
raise ValueError("Empty data list")
|
||||
person = data[0]
|
||||
workflow.set_state("total_records", len(data))
|
||||
workflow.set_state("current_index", 0)
|
||||
workflow.set_state("remaining", len(data) - 1)
|
||||
print(f"[DEBUG] First record from list of {len(data)} items")
|
||||
else:
|
||||
raise ValueError("Input must be a dictionary or list with at least one record")
|
||||
|
||||
processed_person = person.copy()
|
||||
|
||||
# Add salary category
|
||||
salary = person.get("salary", 0)
|
||||
if salary < 50000:
|
||||
processed_person["salary_category"] = "entry"
|
||||
elif salary < 90000:
|
||||
processed_person["salary_category"] = "mid"
|
||||
else:
|
||||
processed_person["salary_category"] = "senior"
|
||||
|
||||
# Add age group
|
||||
age = person.get("age", 0)
|
||||
if age < 35:
|
||||
processed_person["age_group"] = "young"
|
||||
elif age < 50:
|
||||
processed_person["age_group"] = "mid"
|
||||
else:
|
||||
processed_person["age_group"] = "senior"
|
||||
|
||||
# Add processing status using workflow state
|
||||
remaining = workflow.get_state("remaining", 0)
|
||||
current_index = workflow.get_state("current_index", 0)
|
||||
total_records = workflow.get_state("total_records", 1)
|
||||
|
||||
# Update current index for next iteration
|
||||
workflow.set_state("current_index", current_index + 1)
|
||||
|
||||
print(f"[DEBUG] Status check - remaining: {remaining}, current_index: {current_index}, total_records: {total_records}")
|
||||
|
||||
if remaining <= 0 and current_index >= total_records - 1:
|
||||
print("[DEBUG] Setting status to 'all records processed'")
|
||||
processed_person["processing_status"] = "all records processed"
|
||||
else:
|
||||
print(f"[DEBUG] More records to process. Remaining: {remaining}")
|
||||
processed_person["processing_status"] = f"more records to process ({remaining} remaining)"
|
||||
|
||||
print("[DEBUG] Final processed person:", processed_person)
|
||||
return processed_person
|
||||
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] Error processing data: {str(e)}")
|
||||
return {"error": str(e), "processing_status": "error occurred"}
|
||||
|
||||
# Create agents
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Data collection specialist",
|
||||
goal="Collect and validate data about individuals",
|
||||
backstory="Expert in gathering and validating demographic data",
|
||||
tools=[random_data_of_individuals],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
process_agent = Agent(
|
||||
name="DataProcessor",
|
||||
role="Data processor",
|
||||
goal="Process and categorize individual data",
|
||||
backstory="Expert in data analysis and categorization",
|
||||
tools=[process_data_of_individuals],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Modify tasks to use Pydantic models
|
||||
collect_task = Task(
|
||||
description="Collect random individual data using the random_data_of_individuals tool. Return as a JSON object with 'items' array.",
|
||||
expected_output="List of individual records with basic information",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
tools=[random_data_of_individuals],
|
||||
is_start=True,
|
||||
next_tasks=["validate_data"],
|
||||
output_json=DataList
|
||||
)
|
||||
|
||||
validate_task = Task(
|
||||
description="""Validate the collected data. Check if:
|
||||
1. All required fields are present (name, age, job, city, salary)
|
||||
2. Age is between 25 and 65
|
||||
3. Salary is between 30000 and 120000
|
||||
Return validation_result as 'valid' or 'invalid' with optional details.""",
|
||||
expected_output="Validation result indicating if data is valid or invalid",
|
||||
agent=data_agent,
|
||||
name="validate_data",
|
||||
task_type="decision",
|
||||
condition={
|
||||
"valid": ["process_data"],
|
||||
"invalid": ["collect_data"]
|
||||
},
|
||||
output_json=ValidationResult
|
||||
)
|
||||
|
||||
process_task = Task(
|
||||
description="""Process one record at a time from the input data.
|
||||
Current progress will be shown in Loop Status.
|
||||
|
||||
For the current record:
|
||||
1. Use process_data_of_individuals tool to add categories
|
||||
2. Return the processed record with remaining count
|
||||
|
||||
Current remaining: {remaining}
|
||||
Current item: {current_item}
|
||||
|
||||
Process this record and indicate if more records remain.""",
|
||||
expected_output="Processed record with categories and status",
|
||||
agent=process_agent,
|
||||
name="process_data",
|
||||
tools=[process_data_of_individuals],
|
||||
task_type="loop",
|
||||
condition={
|
||||
"more records to process": ["process_data"],
|
||||
"all records processed": []
|
||||
},
|
||||
context=[collect_task],
|
||||
output_json=ProcessedPerson
|
||||
)
|
||||
|
||||
# Create PraisonAIAgents instance with workflow process
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[data_agent, process_agent],
|
||||
tasks=[collect_task, validate_task, process_task],
|
||||
verbose=1,
|
||||
process="workflow"
|
||||
)
|
||||
|
||||
# Run the workflow
|
||||
result = workflow.start()
|
||||
|
||||
# Print results
|
||||
print("\nWorkflow Results:")
|
||||
print("----------------")
|
||||
for task_id, task in workflow.tasks.items():
|
||||
print(f"\nTask: {task.name}")
|
||||
print(f"Status: {task.status}")
|
||||
if task.result:
|
||||
print("Output:")
|
||||
try:
|
||||
# Try to format as pretty JSON
|
||||
import json
|
||||
output = json.loads(task.result.raw)
|
||||
print(json.dumps(output, indent=2))
|
||||
except:
|
||||
# If not JSON, print raw output
|
||||
print(task.result.raw[:500] + "..." if len(task.result.raw) > 500 else task.result.raw)
|
||||
@@ -1 +0,0 @@
|
||||
# Welcome to Praison AI! 🚀🤖
|
||||
@@ -0,0 +1,2 @@
|
||||
*.txt
|
||||
*.csv
|
||||
@@ -1,42 +0,0 @@
|
||||
framework: crewai
|
||||
topic: create a movie about cat in mars based on https://blog.celtx.com/how-to-write-a-good-story/
|
||||
roles:
|
||||
story_developer:
|
||||
backstory: Experienced in crafting compelling narratives for a diverse audience.
|
||||
goal: Develop an engaging storyline for a movie about cats in Mars
|
||||
role: Story Developer
|
||||
tasks:
|
||||
storyline_creation:
|
||||
description: Create a captivating storyline for a movie about cats in Mars
|
||||
inspired by the blog post at https://blog.celtx.com/how-to-write-a-good-story/
|
||||
expected_output: Detailed storyline with key plot points, character motivations,
|
||||
and setting descriptions.
|
||||
tools:
|
||||
- 'ScrapeWebsiteTool'
|
||||
screenwriter:
|
||||
backstory: Proficient in translating complex narratives into engaging screenplay
|
||||
format.
|
||||
goal: Transform the storyline into a script
|
||||
role: Screenwriter
|
||||
tasks:
|
||||
script_creation:
|
||||
description: Transform the developed storyline into a script for the movie
|
||||
about cats in Mars.
|
||||
expected_output: Complete script with dialogues, scenes, and stage directions
|
||||
ready for production.
|
||||
tools:
|
||||
- ''
|
||||
director:
|
||||
backstory: Experienced in visual storytelling and bringing scripts to life on
|
||||
screen.
|
||||
goal: Oversee the production of the movie
|
||||
role: Director
|
||||
tasks:
|
||||
movie_production:
|
||||
description: Take the script and lead the team to produce the movie 'Cats
|
||||
in Mars' based on the provided content and script.
|
||||
expected_output: Completed movie ready for distribution with compelling visuals
|
||||
and engaging storytelling.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
@@ -1,42 +0,0 @@
|
||||
framework: crewai
|
||||
topic: create a movie about cat in mars based on https://www.grammarly.com/blog/how-to-write-a-story/
|
||||
roles:
|
||||
story_developer:
|
||||
backstory: Experienced in crafting compelling narratives for a diverse audience.
|
||||
goal: Develop an engaging storyline for a movie about cats in Mars
|
||||
role: Story Developer
|
||||
tasks:
|
||||
storyline_creation:
|
||||
description: Create a captivating storyline for a movie about cats in Mars
|
||||
inspired by the blog post at https://www.grammarly.com/blog/how-to-write-a-story/
|
||||
expected_output: Detailed storyline with key plot points, character motivations,
|
||||
and setting descriptions.
|
||||
tools:
|
||||
- 'ScrapeWebsiteTool'
|
||||
screenwriter:
|
||||
backstory: Proficient in translating complex narratives into engaging screenplay
|
||||
format.
|
||||
goal: Transform the storyline into a script
|
||||
role: Screenwriter
|
||||
tasks:
|
||||
script_creation:
|
||||
description: Transform the developed storyline into a script for the movie
|
||||
about cats in Mars.
|
||||
expected_output: Complete script with dialogues, scenes, and stage directions
|
||||
ready for production.
|
||||
tools:
|
||||
- ''
|
||||
director:
|
||||
backstory: Experienced in visual storytelling and bringing scripts to life on
|
||||
screen.
|
||||
goal: Oversee the production of the movie
|
||||
role: Director
|
||||
tasks:
|
||||
movie_production:
|
||||
description: Take the script and lead the team to produce the movie 'Cats
|
||||
in Mars' based on the provided content and script.
|
||||
expected_output: Completed movie ready for distribution with compelling visuals
|
||||
and engaging storytelling.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
@@ -1,41 +0,0 @@
|
||||
framework: "crewai"
|
||||
topic: "Artificial Intelligence"
|
||||
|
||||
roles:
|
||||
researcher:
|
||||
role: "Senior Data Researcher"
|
||||
goal: "Uncover cutting-edge developments in {topic}"
|
||||
backstory: >
|
||||
You're a seasoned researcher with a knack for uncovering the latest
|
||||
developments in {topic}. Known for your ability to find the most relevant
|
||||
information and present it in a clear and concise manner.
|
||||
tools:
|
||||
- search_tool:
|
||||
engine: google
|
||||
tasks:
|
||||
research_task:
|
||||
description: >
|
||||
Conduct thorough research about {topic}, focusing on the latest
|
||||
trends and technologies.
|
||||
expected_output: >
|
||||
A list of 10 bullet points summarizing key findings with links to
|
||||
relevant sources.
|
||||
|
||||
reporting_analyst:
|
||||
role: "Reporting Analyst"
|
||||
goal: "Create detailed reports based on {topic} data analysis and research findings."
|
||||
backstory: >
|
||||
You're a meticulous analyst with a keen eye for detail. You're known for
|
||||
your ability to turn complex data into clear and concise reports, making
|
||||
it easy for others to understand and act on the information you provide.
|
||||
tasks:
|
||||
reporting_task:
|
||||
description: >
|
||||
Review the research findings and create a comprehensive report on
|
||||
{topic}. Include insights, potential opportunities, and recommendations.
|
||||
expected_output: >
|
||||
A well-structured report in Markdown format, ready for distribution.
|
||||
|
||||
dependencies:
|
||||
- task: reporting_task
|
||||
depends_on: research_task
|
||||
@@ -1,41 +0,0 @@
|
||||
framework: "autogen"
|
||||
topic: "Artificial Intelligence"
|
||||
|
||||
roles:
|
||||
narrative_designer:
|
||||
role: "Narrative Designer"
|
||||
goal: "Craft engaging storylines and narratives for {topic}"
|
||||
backstory: >
|
||||
You're a creative visionary skilled in weaving complex narratives and
|
||||
developing engaging story worlds within {topic}. Your expertise lies in
|
||||
conceptualizing the overarching story and ensuring it resonates with the audience.
|
||||
tasks:
|
||||
story_concept_development:
|
||||
description: >
|
||||
Develop a compelling story concept for {topic}, focusing on originality,
|
||||
thematic depth, and audience engagement. Outline the main narrative arcs,
|
||||
characters, and settings.
|
||||
expected_output: >
|
||||
A comprehensive document outlining the story concept, including key narrative
|
||||
arcs, character bios, and settings descriptions.
|
||||
|
||||
scriptwriter:
|
||||
role: "Scriptwriter"
|
||||
goal: "Transform story concepts into detailed scripts for {topic}"
|
||||
backstory: >
|
||||
With a flair for dialogue and a deep understanding of pacing and structure,
|
||||
you excel at bringing narratives to life through scriptwriting. Your work
|
||||
turns story concepts into blueprints for compelling {topic} experiences.
|
||||
tasks:
|
||||
scriptwriting_task:
|
||||
description: >
|
||||
Based on the narrative concept, write a detailed script for {topic}.
|
||||
Include dialogue, stage directions, and scene descriptions that bring
|
||||
the story to life.
|
||||
expected_output: >
|
||||
A detailed script ready for production, including dialogue, stage
|
||||
directions, and scene descriptions.
|
||||
|
||||
dependencies:
|
||||
- task: scriptwriting_task
|
||||
depends_on: story_concept_development
|
||||
@@ -1,43 +0,0 @@
|
||||
framework: crewai
|
||||
topic: research about nvidia growth
|
||||
roles:
|
||||
data_collector:
|
||||
backstory: An experienced researcher with the ability to efficiently collect and
|
||||
organize vast amounts of data.
|
||||
goal: Gather information on Nvidia's growth
|
||||
role: Data Collector
|
||||
tasks:
|
||||
data_collection_task:
|
||||
description: Collect data on Nvidia's growth from various sources such as
|
||||
financial reports, news articles, and company announcements.
|
||||
expected_output: A comprehensive document detailing data points on Nvidia's
|
||||
growth over the years.
|
||||
tools:
|
||||
- 'YouSearchTool'
|
||||
data_analyst:
|
||||
backstory: Specializes in extracting insights from large datasets, proficient
|
||||
in quantitative and qualitative analysis.
|
||||
goal: Analyze the collected data to identify trends and patterns
|
||||
role: Data Analyst
|
||||
tasks:
|
||||
data_analysis_task:
|
||||
description: Analyze the collected data to identify key trends and patterns
|
||||
in Nvidia's growth.
|
||||
expected_output: An analytical report summarizing trends, patterns, and key
|
||||
growth metrics of Nvidia.
|
||||
tools:
|
||||
- ''
|
||||
report_preparer:
|
||||
backstory: Experienced in creating detailed reports and presentations, turning
|
||||
analytical data into actionable insights.
|
||||
goal: Generate a final report on Nvidia's growth
|
||||
role: Report Preparer
|
||||
tasks:
|
||||
report_preparation_task:
|
||||
description: Create a detailed report based on the analysis, highlighting
|
||||
Nvidia's growth trajectory.
|
||||
expected_output: A polished, comprehensive report summarizing Nvidia's growth
|
||||
with visual aids and key insights.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
@@ -1,26 +0,0 @@
|
||||
framework: crewai
|
||||
topic: research about the latest AI News and prepare a detailed report
|
||||
roles:
|
||||
research_analyst:
|
||||
backstory: Experienced in gathering and analyzing data related to AI news trends.
|
||||
goal: Analyze AI News trends
|
||||
role: Research Analyst
|
||||
tasks:
|
||||
gather_data:
|
||||
description: Conduct in-depth research on the latest AI News trends from reputable
|
||||
sources.
|
||||
expected_output: Comprehensive report on current AI News trends.
|
||||
tools:
|
||||
- 'InternetSearchTool'
|
||||
content_creator:
|
||||
backstory: Skilled in writing informative and engaging content about AI News.
|
||||
goal: Create detailed reports on AI News
|
||||
role: Content Creator
|
||||
tasks:
|
||||
compile_report:
|
||||
description: Compile all gathered data into a detailed report with analysis
|
||||
and insights.
|
||||
expected_output: Well-structured report on the latest AI News with key insights.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
@@ -1,39 +0,0 @@
|
||||
framework: crewai
|
||||
topic: research about the causes of lung disease
|
||||
roles:
|
||||
research_analyst:
|
||||
backstory: Experienced in analyzing scientific data related to respiratory health.
|
||||
goal: Analyze data on lung diseases
|
||||
role: Research Analyst
|
||||
tasks:
|
||||
data_analysis:
|
||||
description: Gather and analyze data on the causes and risk factors of lung
|
||||
diseases.
|
||||
expected_output: Report detailing key findings on lung disease causes.
|
||||
tools:
|
||||
- 'PubmedQueryRun'
|
||||
medical_writer:
|
||||
backstory: Skilled in translating complex medical information into accessible
|
||||
content.
|
||||
goal: Compile comprehensive content on lung disease causes
|
||||
role: Medical Writer
|
||||
tasks:
|
||||
content_creation:
|
||||
description: Create detailed content summarizing the research findings on
|
||||
lung disease causes.
|
||||
expected_output: Document outlining various causes and risk factors of lung
|
||||
diseases.
|
||||
tools:
|
||||
- ''
|
||||
editor:
|
||||
backstory: Proficient in editing medical content for accuracy and clarity.
|
||||
goal: Review and refine content on lung disease causes
|
||||
role: Editor
|
||||
tasks:
|
||||
content_review:
|
||||
description: Edit and refine the compiled content on lung disease causes for
|
||||
accuracy and coherence.
|
||||
expected_output: Finalized document on lung disease causes ready for dissemination.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
@@ -1,311 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"id": "cW47IVIvdyii",
|
||||
"outputId": "dad73c8c-7506-440b-da37-8d8b21f7813f",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/173.7 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m173.7/173.7 kB\u001b[0m \u001b[31m5.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.9/40.9 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.3/67.3 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
"\u001b[33mWARNING: embedchain 0.1.124 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.124 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.123 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.123 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.122 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.122 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.121 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.121 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.120 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.120 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.119 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.119 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.118 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.118 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.117 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.117 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m160.7/160.7 kB\u001b[0m \u001b[31m11.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.2/76.2 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.2/50.2 kB\u001b[0m \u001b[31m5.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.3/54.3 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.0/1.0 MB\u001b[0m \u001b[31m47.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m525.5/525.5 kB\u001b[0m \u001b[31m40.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m72.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m55.3/55.3 kB\u001b[0m \u001b[31m5.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m202.6/202.6 kB\u001b[0m \u001b[31m19.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m327.6/327.6 kB\u001b[0m \u001b[31m30.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m115.1/115.1 kB\u001b[0m \u001b[31m11.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.6/21.6 MB\u001b[0m \u001b[31m73.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m64.0/64.0 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m52.5/52.5 kB\u001b[0m \u001b[31m4.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m110.5/110.5 kB\u001b[0m \u001b[31m10.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m149.7/149.7 kB\u001b[0m \u001b[31m13.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m342.3/342.3 kB\u001b[0m \u001b[31m29.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m57.6/57.6 kB\u001b[0m \u001b[31m5.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m774.0/774.0 kB\u001b[0m \u001b[31m42.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.7/9.7 MB\u001b[0m \u001b[31m38.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m233.2/233.2 kB\u001b[0m \u001b[31m19.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m273.8/273.8 kB\u001b[0m \u001b[31m19.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m172.8/172.8 kB\u001b[0m \u001b[31m13.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.7/67.7 kB\u001b[0m \u001b[31m5.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m94.7/94.7 kB\u001b[0m \u001b[31m7.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m131.6/131.6 kB\u001b[0m \u001b[31m10.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.9/1.9 MB\u001b[0m \u001b[31m67.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m71.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m302.9/302.9 kB\u001b[0m \u001b[31m23.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m93.2/93.2 kB\u001b[0m \u001b[31m8.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.2/13.2 MB\u001b[0m \u001b[31m88.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m53.0/53.0 kB\u001b[0m \u001b[31m4.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.4/54.4 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.4/5.4 MB\u001b[0m \u001b[31m85.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m342.2/342.2 kB\u001b[0m \u001b[31m28.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m295.8/295.8 kB\u001b[0m \u001b[31m22.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m71.1/71.1 kB\u001b[0m \u001b[31m6.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m58.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m481.7/481.7 kB\u001b[0m \u001b[31m34.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m63.7/63.7 kB\u001b[0m \u001b[31m6.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.0/3.0 MB\u001b[0m \u001b[31m81.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m254.9/254.9 kB\u001b[0m \u001b[31m23.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m248.1/248.1 kB\u001b[0m \u001b[31m23.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m442.1/442.1 kB\u001b[0m \u001b[31m36.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.5/49.5 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m98.7/98.7 kB\u001b[0m \u001b[31m9.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m856.7/856.7 kB\u001b[0m \u001b[31m48.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m73.3/73.3 kB\u001b[0m \u001b[31m7.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m14.0/14.0 MB\u001b[0m \u001b[31m75.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.8/3.8 MB\u001b[0m \u001b[31m91.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m425.7/425.7 kB\u001b[0m \u001b[31m32.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m164.1/164.1 kB\u001b[0m \u001b[31m14.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.0/3.0 MB\u001b[0m \u001b[31m78.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m78.6/78.6 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.4/194.4 kB\u001b[0m \u001b[31m18.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m72.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m80.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m8.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.7/1.7 MB\u001b[0m \u001b[31m67.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h Building wheel for praisonai (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Building wheel for docx2txt (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Building wheel for pypika (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!pip install -Uq \"praisonai[crewai]\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000
|
||||
},
|
||||
"id": "myh-_QCuHfOs",
|
||||
"outputId": "5384b8e0-e56c-4833-a829-2593ba6c6393"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[1m\u001b[95m [2024-10-31 21:43:52][DEBUG]: == Working Agent: Space Researcher\u001b[00m\n",
|
||||
"\u001b[1m\u001b[95m [2024-10-31 21:43:52][INFO]: == Starting Task: Research and compile information about exoplanets discovered in the last decade.\u001b[00m\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\u001b[1m> Entering new CrewAgentExecutor chain...\u001b[0m\n",
|
||||
"\u001b[32;1m\u001b[1;3mThought: I now can give a great answer \n",
|
||||
"Final Answer: my best complete final answer to the task. \n",
|
||||
"Over the last decade, the field of exoplanet research has experienced remarkable advancements, leading to the discovery of thousands of new planets beyond our solar system. Here is a summarized report on some of the most significant exoplanet discoveries in terms of their size, potential habitability, and distance from Earth:\n",
|
||||
"\n",
|
||||
"1. **Kepler-452b**: Discovered in 2015 by NASA's Kepler mission, Kepler-452b is often referred to as Earth's \"cousin.\" It is about 1.6 times the size of Earth and orbits within the habitable zone of a G-type star similar to our Sun, located approximately 1,400 light-years away from Earth. Its potential for hosting life lies in its Earth-like characteristics, though its actual habitability remains uncertain due to its distance and lack of detailed atmospheric data.\n",
|
||||
"\n",
|
||||
"2. **Proxima Centauri b**: Found in 2016, this exoplanet orbits the closest star to our solar system, Proxima Centauri, at a distance of just 4.24 light-years. Proxima Centauri b is roughly 1.27 times the size of Earth and resides within the star's habitable zone, where liquid water could potentially exist. Its proximity makes it a prime candidate for future studies on habitability and atmospheric composition.\n",
|
||||
"\n",
|
||||
"3. **TRAPPIST-1 System**: Discovered in 2017, the TRAPPIST-1 system contains seven Earth-sized exoplanets, three of which lie in the star's habitable zone. Located about 39 light-years away, these planets are of significant interest due to their potential for liquid water. The compact nature of the system and the small, cool star around which they orbit make them excellent targets for atmospheric studies using telescopes like the James Webb Space Telescope.\n",
|
||||
"\n",
|
||||
"4. **LHS 1140 b**: This exoplanet was discovered in 2017 and is located approximately 41 light-years away. It is about 1.4 times the size of Earth and orbits within the habitable zone of a red dwarf star. Its dense, rocky composition and the presence of a substantial atmosphere make it a compelling candidate for habitability studies.\n",
|
||||
"\n",
|
||||
"5. **K2-18b**: Announced in 2019, K2-18b is situated 124 light-years from Earth and is a super-Earth with a mass about 8 times that of our planet. It orbits within the habitable zone of its star, and water vapor has been detected in its atmosphere, making it one of the most intriguing exoplanets in terms of potential habitability.\n",
|
||||
"\n",
|
||||
"These discoveries highlight the diversity of exoplanets in terms of size, composition, and orbit, as well as the progress made in identifying worlds that could potentially host life. Advances in technology and observational techniques continue to enhance our understanding of these distant worlds, bringing us closer to answering the age-old question of whether we are alone in the universe.\u001b[0m\n",
|
||||
"\n",
|
||||
"\u001b[1m> Finished chain.\u001b[0m\n",
|
||||
"\u001b[1m\u001b[92m [2024-10-31 21:44:05][DEBUG]: == [Space Researcher] Task output: my best complete final answer to the task. \n",
|
||||
"Over the last decade, the field of exoplanet research has experienced remarkable advancements, leading to the discovery of thousands of new planets beyond our solar system. Here is a summarized report on some of the most significant exoplanet discoveries in terms of their size, potential habitability, and distance from Earth:\n",
|
||||
"\n",
|
||||
"1. **Kepler-452b**: Discovered in 2015 by NASA's Kepler mission, Kepler-452b is often referred to as Earth's \"cousin.\" It is about 1.6 times the size of Earth and orbits within the habitable zone of a G-type star similar to our Sun, located approximately 1,400 light-years away from Earth. Its potential for hosting life lies in its Earth-like characteristics, though its actual habitability remains uncertain due to its distance and lack of detailed atmospheric data.\n",
|
||||
"\n",
|
||||
"2. **Proxima Centauri b**: Found in 2016, this exoplanet orbits the closest star to our solar system, Proxima Centauri, at a distance of just 4.24 light-years. Proxima Centauri b is roughly 1.27 times the size of Earth and resides within the star's habitable zone, where liquid water could potentially exist. Its proximity makes it a prime candidate for future studies on habitability and atmospheric composition.\n",
|
||||
"\n",
|
||||
"3. **TRAPPIST-1 System**: Discovered in 2017, the TRAPPIST-1 system contains seven Earth-sized exoplanets, three of which lie in the star's habitable zone. Located about 39 light-years away, these planets are of significant interest due to their potential for liquid water. The compact nature of the system and the small, cool star around which they orbit make them excellent targets for atmospheric studies using telescopes like the James Webb Space Telescope.\n",
|
||||
"\n",
|
||||
"4. **LHS 1140 b**: This exoplanet was discovered in 2017 and is located approximately 41 light-years away. It is about 1.4 times the size of Earth and orbits within the habitable zone of a red dwarf star. Its dense, rocky composition and the presence of a substantial atmosphere make it a compelling candidate for habitability studies.\n",
|
||||
"\n",
|
||||
"5. **K2-18b**: Announced in 2019, K2-18b is situated 124 light-years from Earth and is a super-Earth with a mass about 8 times that of our planet. It orbits within the habitable zone of its star, and water vapor has been detected in its atmosphere, making it one of the most intriguing exoplanets in terms of potential habitability.\n",
|
||||
"\n",
|
||||
"These discoveries highlight the diversity of exoplanets in terms of size, composition, and orbit, as well as the progress made in identifying worlds that could potentially host life. Advances in technology and observational techniques continue to enhance our understanding of these distant worlds, bringing us closer to answering the age-old question of whether we are alone in the universe.\n",
|
||||
"\n",
|
||||
"\u001b[00m\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"### Task Output ###\n",
|
||||
"my best complete final answer to the task. \n",
|
||||
"Over the last decade, the field of exoplanet research has experienced remarkable advancements, leading to the \n",
|
||||
"discovery of thousands of new planets beyond our solar system. Here is a summarized report on some of the most \n",
|
||||
"significant exoplanet discoveries in terms of their size, potential habitability, and distance from Earth:\n",
|
||||
"\n",
|
||||
"\u001b[1;36m1\u001b[0m. **Kepler-452b**: Discovered in \u001b[1;36m2015\u001b[0m by NASA's Kepler mission, Kepler-452b is often referred to as Earth's \n",
|
||||
"\u001b[32m\"cousin.\"\u001b[0m It is about \u001b[1;36m1.6\u001b[0m times the size of Earth and orbits within the habitable zone of a G-type star similar to \n",
|
||||
"our Sun, located approximately \u001b[1;36m1\u001b[0m,\u001b[1;36m400\u001b[0m light-years away from Earth. Its potential for hosting life lies in its \n",
|
||||
"Earth-like characteristics, though its actual habitability remains uncertain due to its distance and lack of \n",
|
||||
"detailed atmospheric data.\n",
|
||||
"\n",
|
||||
"\u001b[1;36m2\u001b[0m. **Proxima Centauri b**: Found in \u001b[1;36m2016\u001b[0m, this exoplanet orbits the closest star to our solar system, Proxima \n",
|
||||
"Centauri, at a distance of just \u001b[1;36m4.24\u001b[0m light-years. Proxima Centauri b is roughly \u001b[1;36m1.27\u001b[0m times the size of Earth and \n",
|
||||
"resides within the star's habitable zone, where liquid water could potentially exist. Its proximity makes it a \n",
|
||||
"prime candidate for future studies on habitability and atmospheric composition.\n",
|
||||
"\n",
|
||||
"\u001b[1;36m3\u001b[0m. **TRAPPIST-\u001b[1;36m1\u001b[0m System**: Discovered in \u001b[1;36m2017\u001b[0m, the TRAPPIST-\u001b[1;36m1\u001b[0m system contains seven Earth-sized exoplanets, three of\n",
|
||||
"which lie in the star's habitable zone. Located about \u001b[1;36m39\u001b[0m light-years away, these planets are of significant \n",
|
||||
"interest due to their potential for liquid water. The compact nature of the system and the small, cool star around \n",
|
||||
"which they orbit make them excellent targets for atmospheric studies using telescopes like the James Webb Space \n",
|
||||
"Telescope.\n",
|
||||
"\n",
|
||||
"\u001b[1;36m4\u001b[0m. **LHS \u001b[1;36m1140\u001b[0m b**: This exoplanet was discovered in \u001b[1;36m2017\u001b[0m and is located approximately \u001b[1;36m41\u001b[0m light-years away. It is \n",
|
||||
"about \u001b[1;36m1.4\u001b[0m times the size of Earth and orbits within the habitable zone of a red dwarf star. Its dense, rocky \n",
|
||||
"composition and the presence of a substantial atmosphere make it a compelling candidate for habitability studies.\n",
|
||||
"\n",
|
||||
"\u001b[1;36m5\u001b[0m. **K2-18b**: Announced in \u001b[1;36m2019\u001b[0m, K2-18b is situated \u001b[1;36m124\u001b[0m light-years from Earth and is a super-Earth with a mass \n",
|
||||
"about \u001b[1;36m8\u001b[0m times that of our planet. It orbits within the habitable zone of its star, and water vapor has been \n",
|
||||
"detected in its atmosphere, making it one of the most intriguing exoplanets in terms of potential habitability.\n",
|
||||
"\n",
|
||||
"These discoveries highlight the diversity of exoplanets in terms of size, composition, and orbit, as well as the \n",
|
||||
"progress made in identifying worlds that could potentially host life. Advances in technology and observational \n",
|
||||
"techniques continue to enhance our understanding of these distant worlds, bringing us closer to answering the \n",
|
||||
"age-old question of whether we are alone in the universe.\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">### Task Output ###\n",
|
||||
"my best complete final answer to the task. \n",
|
||||
"Over the last decade, the field of exoplanet research has experienced remarkable advancements, leading to the \n",
|
||||
"discovery of thousands of new planets beyond our solar system. Here is a summarized report on some of the most \n",
|
||||
"significant exoplanet discoveries in terms of their size, potential habitability, and distance from Earth:\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>. **Kepler-452b**: Discovered in <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2015</span> by NASA's Kepler mission, Kepler-452b is often referred to as Earth's \n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">\"cousin.\"</span> It is about <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1.6</span> times the size of Earth and orbits within the habitable zone of a G-type star similar to \n",
|
||||
"our Sun, located approximately <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>,<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">400</span> light-years away from Earth. Its potential for hosting life lies in its \n",
|
||||
"Earth-like characteristics, though its actual habitability remains uncertain due to its distance and lack of \n",
|
||||
"detailed atmospheric data.\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span>. **Proxima Centauri b**: Found in <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2016</span>, this exoplanet orbits the closest star to our solar system, Proxima \n",
|
||||
"Centauri, at a distance of just <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4.24</span> light-years. Proxima Centauri b is roughly <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1.27</span> times the size of Earth and \n",
|
||||
"resides within the star's habitable zone, where liquid water could potentially exist. Its proximity makes it a \n",
|
||||
"prime candidate for future studies on habitability and atmospheric composition.\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3</span>. **TRAPPIST-<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span> System**: Discovered in <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2017</span>, the TRAPPIST-<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span> system contains seven Earth-sized exoplanets, three of\n",
|
||||
"which lie in the star's habitable zone. Located about <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">39</span> light-years away, these planets are of significant \n",
|
||||
"interest due to their potential for liquid water. The compact nature of the system and the small, cool star around \n",
|
||||
"which they orbit make them excellent targets for atmospheric studies using telescopes like the James Webb Space \n",
|
||||
"Telescope.\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4</span>. **LHS <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1140</span> b**: This exoplanet was discovered in <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2017</span> and is located approximately <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">41</span> light-years away. It is \n",
|
||||
"about <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1.4</span> times the size of Earth and orbits within the habitable zone of a red dwarf star. Its dense, rocky \n",
|
||||
"composition and the presence of a substantial atmosphere make it a compelling candidate for habitability studies.\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">5</span>. **K2-18b**: Announced in <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2019</span>, K2-18b is situated <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">124</span> light-years from Earth and is a super-Earth with a mass \n",
|
||||
"about <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">8</span> times that of our planet. It orbits within the habitable zone of its star, and water vapor has been \n",
|
||||
"detected in its atmosphere, making it one of the most intriguing exoplanets in terms of potential habitability.\n",
|
||||
"\n",
|
||||
"These discoveries highlight the diversity of exoplanets in terms of size, composition, and orbit, as well as the \n",
|
||||
"progress made in identifying worlds that could potentially host life. Advances in technology and observational \n",
|
||||
"techniques continue to enhance our understanding of these distant worlds, bringing us closer to answering the \n",
|
||||
"age-old question of whether we are alone in the universe.\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"None\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import yaml\n",
|
||||
"from praisonai import PraisonAI\n",
|
||||
"from google.colab import userdata\n",
|
||||
"\n",
|
||||
"# Example agent_yaml content\n",
|
||||
"agent_yaml = \"\"\"\n",
|
||||
"framework: \"crewai\"\n",
|
||||
"topic: \"Space Exploration\"\n",
|
||||
"\n",
|
||||
"roles:\n",
|
||||
" astronomer:\n",
|
||||
" role: \"Space Researcher\"\n",
|
||||
" goal: \"Discover new insights about {topic}\"\n",
|
||||
" backstory: \"You are a curious and dedicated astronomer with a passion for unraveling the mysteries of the cosmos.\"\n",
|
||||
" tasks:\n",
|
||||
" investigate_exoplanets:\n",
|
||||
" description: \"Research and compile information about exoplanets discovered in the last decade.\"\n",
|
||||
" expected_output: \"A summarized report on exoplanet discoveries, including their size, potential habitability, and distance from Earth.\"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"# Create a PraisonAI instance with the agent_yaml content\n",
|
||||
"praisonai = PraisonAI(agent_yaml=agent_yaml)\n",
|
||||
"\n",
|
||||
"# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY') or \"ENTER OPENAI_API_KEY HERE\"\n",
|
||||
"\n",
|
||||
"# Run PraisonAI\n",
|
||||
"result = praisonai.run()\n",
|
||||
"\n",
|
||||
"# Print the result\n",
|
||||
"print(result)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"accelerator": "GPU",
|
||||
"colab": {
|
||||
"gpuType": "T4",
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "MHwYRTSdlNUS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"id": "cW47IVIvdyii",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"outputId": "ad31a979-acb4-4200-9ce8-439ab4193594"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/173.7 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m173.7/173.7 kB\u001b[0m \u001b[31m8.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.9/40.9 kB\u001b[0m \u001b[31m3.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.3/67.3 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
"\u001b[33mWARNING: embedchain 0.1.124 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.124 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.123 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.123 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.122 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.122 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.121 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.121 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.120 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.120 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.119 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.119 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.118 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.118 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.117 does not provide the extra 'github'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m\u001b[33mWARNING: embedchain 0.1.117 does not provide the extra 'youtube'\u001b[0m\u001b[33m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m160.7/160.7 kB\u001b[0m \u001b[31m13.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.2/76.2 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.2/50.2 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.3/54.3 kB\u001b[0m \u001b[31m4.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.0/1.0 MB\u001b[0m \u001b[31m46.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.0/3.0 MB\u001b[0m \u001b[31m13.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m525.5/525.5 kB\u001b[0m \u001b[31m32.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m18.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m55.3/55.3 kB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m202.6/202.6 kB\u001b[0m \u001b[31m16.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m327.6/327.6 kB\u001b[0m \u001b[31m25.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m115.1/115.1 kB\u001b[0m \u001b[31m7.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.6/21.6 MB\u001b[0m \u001b[31m39.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m64.0/64.0 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m52.5/52.5 kB\u001b[0m \u001b[31m4.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m110.5/110.5 kB\u001b[0m \u001b[31m10.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m149.7/149.7 kB\u001b[0m \u001b[31m14.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m342.3/342.3 kB\u001b[0m \u001b[31m22.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m57.6/57.6 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m774.0/774.0 kB\u001b[0m \u001b[31m9.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.7/9.7 MB\u001b[0m \u001b[31m116.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m233.2/233.2 kB\u001b[0m \u001b[31m19.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m273.8/273.8 kB\u001b[0m \u001b[31m24.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m172.8/172.8 kB\u001b[0m \u001b[31m16.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.7/67.7 kB\u001b[0m \u001b[31m6.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m94.7/94.7 kB\u001b[0m \u001b[31m9.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m131.6/131.6 kB\u001b[0m \u001b[31m13.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.9/1.9 MB\u001b[0m \u001b[31m76.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m84.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m302.9/302.9 kB\u001b[0m \u001b[31m25.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m93.2/93.2 kB\u001b[0m \u001b[31m8.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.2/13.2 MB\u001b[0m \u001b[31m48.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m53.0/53.0 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.4/54.4 kB\u001b[0m \u001b[31m5.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.4/5.4 MB\u001b[0m \u001b[31m15.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m342.2/342.2 kB\u001b[0m \u001b[31m25.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m295.8/295.8 kB\u001b[0m \u001b[31m22.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m71.1/71.1 kB\u001b[0m \u001b[31m2.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m58.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m481.7/481.7 kB\u001b[0m \u001b[31m38.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m63.7/63.7 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.0/3.0 MB\u001b[0m \u001b[31m93.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m254.9/254.9 kB\u001b[0m \u001b[31m21.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m248.1/248.1 kB\u001b[0m \u001b[31m20.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m442.1/442.1 kB\u001b[0m \u001b[31m32.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.5/49.5 kB\u001b[0m \u001b[31m4.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m98.7/98.7 kB\u001b[0m \u001b[31m10.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m856.7/856.7 kB\u001b[0m \u001b[31m53.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m73.3/73.3 kB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m14.0/14.0 MB\u001b[0m \u001b[31m37.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.8/3.8 MB\u001b[0m \u001b[31m72.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m425.7/425.7 kB\u001b[0m \u001b[31m32.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m164.1/164.1 kB\u001b[0m \u001b[31m14.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.0/3.0 MB\u001b[0m \u001b[31m98.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m78.6/78.6 kB\u001b[0m \u001b[31m7.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.4/194.4 kB\u001b[0m \u001b[31m17.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m71.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m94.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.7/1.7 MB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h Building wheel for praisonai (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Building wheel for docx2txt (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
" Building wheel for pypika (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!pip install -Uq \"praisonai[crewai]\" duckduckgo_search"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"id": "Qwds0ad96Pco"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# tools.py\n",
|
||||
"from duckduckgo_search import DDGS\n",
|
||||
"from praisonai_tools import BaseTool\n",
|
||||
"\n",
|
||||
"class InternetSearchTool(BaseTool):\n",
|
||||
" name: str = \"InternetSearchTool\"\n",
|
||||
" description: str = \"Search Internet for relevant information based on a query or latest news\"\n",
|
||||
"\n",
|
||||
" def _run(self, query: str):\n",
|
||||
" ddgs = DDGS()\n",
|
||||
" results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)\n",
|
||||
" return results"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000
|
||||
},
|
||||
"id": "myh-_QCuHfOs",
|
||||
"outputId": "8024c5db-cdf3-4099-cf15-86c33c35f795"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[1m\u001b[95m [2024-10-31 17:13:31][DEBUG]: == Working Agent: Space Researcher\u001b[00m\n",
|
||||
"\u001b[1m\u001b[95m [2024-10-31 17:13:31][INFO]: == Starting Task: Research and compile information about exoplanets discovered in the last decade.\u001b[00m\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\u001b[1m> Entering new CrewAgentExecutor chain...\u001b[0m\n",
|
||||
"\u001b[32;1m\u001b[1;3mTo compile a comprehensive report on exoplanets discovered in the last decade, I should start by searching for relevant information on recent exoplanet discoveries, focusing on their size, potential habitability, and distance from Earth. \n",
|
||||
"\n",
|
||||
"Action: InternetSearchTool\n",
|
||||
"Action Input: {\"query\": \"exoplanets discovered in the last decade size habitability distance from Earth\"}\u001b[0m"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stderr",
|
||||
"text": [
|
||||
"/usr/local/lib/python3.10/dist-packages/pydantic/main.py:214: UserWarning: A custom validator is returning a value other than `self`.\n",
|
||||
"Returning anything other than `self` from a top level model validator isn't supported when validating via `__init__`.\n",
|
||||
"See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.\n",
|
||||
" warnings.warn(\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[95m \n",
|
||||
"\n",
|
||||
"[{'title': 'Earth-Size, Habitable Zone Planet Found Hidden in Early NASA Kepler ...', 'href': 'https://www.nasa.gov/news-release/earth-size-habitable-zone-planet-found-hidden-in-early-nasa-kepler-data/', 'body': \"A team of transatlantic scientists, using reanalyzed data from NASA's Kepler space telescope, has discovered an Earth-size exoplanet orbiting in its star's habitable zone, the area around a star where a rocky planet could support liquid water. Scientists discovered this planet, called Kepler-1649c, when looking through old observations from ...\"}, {'title': 'Largest Batch of Earth-size Habitable Zone Planets Found ...', 'href': 'https://science.nasa.gov/exoplanets/trappist1/', 'body': \"TRAPPIST-1: Largest Batch of Earth-sized Exoplanets The most studied planetary system, aside from our own solar system, lies about 40 light-years away. We've looked at the seven rocky exoplanets orbiting the TRAPPIST-1 star with ground and space telescopes like Spitzer, Kepler, Hubble, and, now, the James Webb Space Telescope. In March 2023, the first science […]\"}, {'title': 'NASA Telescope Reveals Largest Batch of Earth-Size ...', 'href': 'https://www.nasa.gov/news-release/nasa-telescope-reveals-largest-batch-of-earth-size-habitable-zone-planets-around-single-star/', 'body': '\"The seven wonders of TRAPPIST-1 are the first Earth-size planets that have been found orbiting this kind of star,\" said Michael Gillon, lead author of the paper and the principal investigator of the TRAPPIST exoplanet survey at the University of Liege, Belgium. \"It is also the best target yet for studying the atmospheres of potentially ...'}, {'title': 'NASA finds potentially habitable Earth-sized exoplanet ...', 'href': 'https://www.usatoday.com/story/news/nation/2024/05/28/nasa-exoplanet-discovery/73882055007/', 'body': '0:00. 0:59. NASA announced the discovery of a planet 40 light years from Earth that orbits every 12.8 days and is possibly even habitable. Gliese 12 b is a \"super Earth exoplanet\" that is nearly ...'}, {'title': \"NASA space telescope finds Earth-size exoplanet that's\", 'href': 'https://www.space.com/gliese-12-b-tess-exoplanet-hunt-for-life', 'body': \"The exoplanet — which the team found with NASA's Transiting Exoplanet Survey Satellite (TESS) — is estimated to have a width around 1.1 times that of Earth, making it similar to our planet as ...\"}]\n",
|
||||
"\u001b[00m\n",
|
||||
"\u001b[32;1m\u001b[1;3mThought: I have gathered multiple sources discussing exoplanet discoveries, including details about their size, potential habitability, and distance from Earth. I will now compile this information into a comprehensive report.\n",
|
||||
"\n",
|
||||
"Final Answer:\n",
|
||||
"\n",
|
||||
"### Exoplanet Discoveries in the Last Decade\n",
|
||||
"\n",
|
||||
"1. **Kepler-1649c**\n",
|
||||
" - **Size:** Earth-sized\n",
|
||||
" - **Habitability:** This exoplanet orbits in its star's habitable zone, where a rocky planet could support liquid water.\n",
|
||||
" - **Distance from Earth:** Discovered using reanalyzed data from NASA's Kepler space telescope, the exact distance wasn't specified in the initial search result.\n",
|
||||
"\n",
|
||||
"2. **TRAPPIST-1 System**\n",
|
||||
" - **Size:** The system consists of seven Earth-sized exoplanets.\n",
|
||||
" - **Habitability:** The TRAPPIST-1 system is one of the most studied, and it provides the best targets for studying the atmospheres of potentially habitable planets.\n",
|
||||
" - **Distance from Earth:** About 40 light-years away.\n",
|
||||
"\n",
|
||||
"3. **Gliese 12 b**\n",
|
||||
" - **Size:** Classified as a \"super Earth\" exoplanet, with a width approximately 1.1 times that of Earth.\n",
|
||||
" - **Habitability:** Potentially habitable and orbits every 12.8 days, suggesting it could support liquid water.\n",
|
||||
" - **Distance from Earth:** 40 light-years away.\n",
|
||||
"\n",
|
||||
"These discoveries highlight significant strides in identifying exoplanets that resemble Earth in size and orbit within habitable zones. The proximity of these planets, particularly the TRAPPIST-1 system and Gliese 12 b, offers promising opportunities for future exploration and study of potentially habitable worlds beyond our solar system.\u001b[0m\n",
|
||||
"\n",
|
||||
"\u001b[1m> Finished chain.\u001b[0m\n",
|
||||
"\u001b[1m\u001b[92m [2024-10-31 17:13:47][DEBUG]: == [Space Researcher] Task output: ### Exoplanet Discoveries in the Last Decade\n",
|
||||
"\n",
|
||||
"1. **Kepler-1649c**\n",
|
||||
" - **Size:** Earth-sized\n",
|
||||
" - **Habitability:** This exoplanet orbits in its star's habitable zone, where a rocky planet could support liquid water.\n",
|
||||
" - **Distance from Earth:** Discovered using reanalyzed data from NASA's Kepler space telescope, the exact distance wasn't specified in the initial search result.\n",
|
||||
"\n",
|
||||
"2. **TRAPPIST-1 System**\n",
|
||||
" - **Size:** The system consists of seven Earth-sized exoplanets.\n",
|
||||
" - **Habitability:** The TRAPPIST-1 system is one of the most studied, and it provides the best targets for studying the atmospheres of potentially habitable planets.\n",
|
||||
" - **Distance from Earth:** About 40 light-years away.\n",
|
||||
"\n",
|
||||
"3. **Gliese 12 b**\n",
|
||||
" - **Size:** Classified as a \"super Earth\" exoplanet, with a width approximately 1.1 times that of Earth.\n",
|
||||
" - **Habitability:** Potentially habitable and orbits every 12.8 days, suggesting it could support liquid water.\n",
|
||||
" - **Distance from Earth:** 40 light-years away.\n",
|
||||
"\n",
|
||||
"These discoveries highlight significant strides in identifying exoplanets that resemble Earth in size and orbit within habitable zones. The proximity of these planets, particularly the TRAPPIST-1 system and Gliese 12 b, offers promising opportunities for future exploration and study of potentially habitable worlds beyond our solar system.\n",
|
||||
"\n",
|
||||
"\u001b[00m\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"### Task Output ###\n",
|
||||
"### Exoplanet Discoveries in the Last Decade\n",
|
||||
"\n",
|
||||
"\u001b[1;36m1\u001b[0m. **Kepler-1649c**\n",
|
||||
" - **Size:** Earth-sized\n",
|
||||
" - **Habitability:** This exoplanet orbits in its star's habitable zone, where a rocky planet could support \n",
|
||||
"liquid water.\n",
|
||||
" - **Distance from Earth:** Discovered using reanalyzed data from NASA's Kepler space telescope, the exact \n",
|
||||
"distance wasn't specified in the initial search result.\n",
|
||||
"\n",
|
||||
"\u001b[1;36m2\u001b[0m. **TRAPPIST-\u001b[1;36m1\u001b[0m System**\n",
|
||||
" - **Size:** The system consists of seven Earth-sized exoplanets.\n",
|
||||
" - **Habitability:** The TRAPPIST-\u001b[1;36m1\u001b[0m system is one of the most studied, and it provides the best targets for \n",
|
||||
"studying the atmospheres of potentially habitable planets.\n",
|
||||
" - **Distance from Earth:** About \u001b[1;36m40\u001b[0m light-years away.\n",
|
||||
"\n",
|
||||
"\u001b[1;36m3\u001b[0m. **Gliese \u001b[1;36m12\u001b[0m b**\n",
|
||||
" - **Size:** Classified as a \u001b[32m\"super Earth\"\u001b[0m exoplanet, with a width approximately \u001b[1;36m1.1\u001b[0m times that of Earth.\n",
|
||||
" - **Habitability:** Potentially habitable and orbits every \u001b[1;36m12.8\u001b[0m days, suggesting it could support liquid water.\n",
|
||||
" - **Distance from Earth:** \u001b[1;36m40\u001b[0m light-years away.\n",
|
||||
"\n",
|
||||
"These discoveries highlight significant strides in identifying exoplanets that resemble Earth in size and orbit \n",
|
||||
"within habitable zones. The proximity of these planets, particularly the TRAPPIST-\u001b[1;36m1\u001b[0m system and Gliese \u001b[1;36m12\u001b[0m b, offers \n",
|
||||
"promising opportunities for future exploration and study of potentially habitable worlds beyond our solar system.\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">### Task Output ###\n",
|
||||
"### Exoplanet Discoveries in the Last Decade\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span>. **Kepler-1649c**\n",
|
||||
" - **Size:** Earth-sized\n",
|
||||
" - **Habitability:** This exoplanet orbits in its star's habitable zone, where a rocky planet could support \n",
|
||||
"liquid water.\n",
|
||||
" - **Distance from Earth:** Discovered using reanalyzed data from NASA's Kepler space telescope, the exact \n",
|
||||
"distance wasn't specified in the initial search result.\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2</span>. **TRAPPIST-<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span> System**\n",
|
||||
" - **Size:** The system consists of seven Earth-sized exoplanets.\n",
|
||||
" - **Habitability:** The TRAPPIST-<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span> system is one of the most studied, and it provides the best targets for \n",
|
||||
"studying the atmospheres of potentially habitable planets.\n",
|
||||
" - **Distance from Earth:** About <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">40</span> light-years away.\n",
|
||||
"\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3</span>. **Gliese <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">12</span> b**\n",
|
||||
" - **Size:** Classified as a <span style=\"color: #008000; text-decoration-color: #008000\">\"super Earth\"</span> exoplanet, with a width approximately <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1.1</span> times that of Earth.\n",
|
||||
" - **Habitability:** Potentially habitable and orbits every <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">12.8</span> days, suggesting it could support liquid water.\n",
|
||||
" - **Distance from Earth:** <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">40</span> light-years away.\n",
|
||||
"\n",
|
||||
"These discoveries highlight significant strides in identifying exoplanets that resemble Earth in size and orbit \n",
|
||||
"within habitable zones. The proximity of these planets, particularly the TRAPPIST-<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span> system and Gliese <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">12</span> b, offers \n",
|
||||
"promising opportunities for future exploration and study of potentially habitable worlds beyond our solar system.\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"None\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import yaml\n",
|
||||
"from praisonai import PraisonAI\n",
|
||||
"from google.colab import userdata\n",
|
||||
"\n",
|
||||
"# Example agent_yaml content\n",
|
||||
"agent_yaml = \"\"\"\n",
|
||||
"framework: \"crewai\"\n",
|
||||
"topic: \"Space Exploration\"\n",
|
||||
"\n",
|
||||
"roles:\n",
|
||||
" astronomer:\n",
|
||||
" role: \"Space Researcher\"\n",
|
||||
" goal: \"Discover new insights about {topic}\"\n",
|
||||
" backstory: \"You are a curious and dedicated astronomer with a passion for unraveling the mysteries of the cosmos.\"\n",
|
||||
" tasks:\n",
|
||||
" investigate_exoplanets:\n",
|
||||
" description: \"Research and compile information about exoplanets discovered in the last decade.\"\n",
|
||||
" expected_output: \"A summarized report on exoplanet discoveries, including their size, potential habitability, and distance from Earth.\"\n",
|
||||
" tools:\n",
|
||||
" - \"InternetSearchTool\"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"# Create a PraisonAI instance with the agent_yaml content\n",
|
||||
"praisonai = PraisonAI(agent_yaml=agent_yaml, tools=[InternetSearchTool])\n",
|
||||
"\n",
|
||||
"# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY') or \"ENTER OPENAI_API_KEY HERE\"\n",
|
||||
"\n",
|
||||
"# Run PraisonAI\n",
|
||||
"result = praisonai.run()\n",
|
||||
"\n",
|
||||
"# Print the result\n",
|
||||
"print(result)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"accelerator": "GPU",
|
||||
"colab": {
|
||||
"gpuType": "T4",
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
# tools.py
|
||||
from langchain_community.utilities import WikipediaAPIWrapper
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class WikipediaSearchTool(BaseTool):
|
||||
name: str = "WikipediaSearchTool"
|
||||
description: str = "Search Wikipedia for relevant information based on a query."
|
||||
|
||||
def _run(self, query: str):
|
||||
api_wrapper = WikipediaAPIWrapper(top_k_results=4, doc_content_chars_max=100)
|
||||
results = api_wrapper.load(query=query)
|
||||
return results
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "research about Nvidia growth"
|
||||
roles:
|
||||
data_collector:
|
||||
role: "Data Collector"
|
||||
backstory: "An experienced researcher with the ability to efficiently collect and organize vast amounts of data."
|
||||
goal: "Gather information on Nvidia's growth by providing the Ticket Symbol to YahooFinanceNewsTool"
|
||||
tasks:
|
||||
data_collection_task:
|
||||
description: "Collect data on Nvidia's growth from various sources such as financial reports, news articles, and company announcements."
|
||||
expected_output: "A comprehensive document detailing data points on Nvidia's growth over the years."
|
||||
tools:
|
||||
- "WikipediaSearchTool"
|
||||
data_analyst:
|
||||
role: "Data Analyst"
|
||||
backstory: "Specializes in extracting insights from large datasets, proficient in quantitative and qualitative analysis."
|
||||
goal: "Analyze the collected data to identify trends and patterns"
|
||||
tasks:
|
||||
data_analysis_task:
|
||||
description: "Analyze the collected data to identify key trends and patterns in Nvidia's growth."
|
||||
expected_output: "An analytical report summarizing trends, patterns, and key growth metrics of Nvidia."
|
||||
tools: []
|
||||
report_preparer:
|
||||
role: "Report Preparer"
|
||||
backstory: "Experienced in creating detailed reports and presentations, turning analytical data into actionable insights."
|
||||
goal: "Generate a final report on Nvidia's growth"
|
||||
tasks:
|
||||
report_preparation_task:
|
||||
description: "Create a detailed report based on the analysis, highlighting Nvidia's growth trajectory."
|
||||
expected_output: "A polished, comprehensive report summarizing Nvidia's growth with visual aids and key insights."
|
||||
tools: []
|
||||
dependencies: []
|
||||
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,97 +0,0 @@
|
||||
# tools.py
|
||||
import os
|
||||
from crawl4ai import WebCrawler
|
||||
from crawl4ai.extraction_strategy import LLMExtractionStrategy
|
||||
from pydantic import BaseModel, Field
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class ModelFee(BaseModel):
|
||||
llm_model_name: str = Field(..., description="Name of the model.")
|
||||
input_fee: str = Field(..., description="Fee for input token for the model.")
|
||||
output_fee: str = Field(..., description="Fee for output token for the model.")
|
||||
|
||||
class ModelFeeTool(BaseTool):
|
||||
name: str = "ModelFeeTool"
|
||||
description: str = "Extracts model fees for input and output tokens from the given pricing page."
|
||||
|
||||
def _run(self, url: str):
|
||||
crawler = WebCrawler()
|
||||
crawler.warmup()
|
||||
|
||||
result = crawler.run(
|
||||
url=url,
|
||||
word_count_threshold=1,
|
||||
extraction_strategy= LLMExtractionStrategy(
|
||||
provider="openai/gpt-4o",
|
||||
api_token=os.getenv('OPENAI_API_KEY'),
|
||||
schema=ModelFee.schema(),
|
||||
extraction_type="schema",
|
||||
instruction="""From the crawled content, extract all mentioned model names along with their fees for input and output tokens.
|
||||
Do not miss any models in the entire content. One extracted model JSON format should look like this:
|
||||
{"model_name": "GPT-4", "input_fee": "US$10.00 / 1M tokens", "output_fee": "US$30.00 / 1M tokens"}."""
|
||||
),
|
||||
bypass_cache=True,
|
||||
)
|
||||
return result.extracted_content
|
||||
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "extract model pricing from websites"
|
||||
roles:
|
||||
web_scraper:
|
||||
role: "Web Scraper"
|
||||
backstory: |
|
||||
An expert in web scraping with a deep understanding of extracting structured
|
||||
data from online sources.
|
||||
|
||||
https://openai.com/api/pricing/
|
||||
https://www.anthropic.com/pricing
|
||||
https://cohere.com/pricing
|
||||
goal: "Gather model pricing data from various websites"
|
||||
tasks:
|
||||
scrape_model_pricing:
|
||||
description: "Scrape model pricing information from the provided list of websites."
|
||||
expected_output: "Raw HTML or JSON containing model pricing data."
|
||||
tools:
|
||||
- "ModelFeeTool"
|
||||
data_cleaner:
|
||||
role: "Data Cleaner"
|
||||
backstory: "Specialist in data cleaning, ensuring that all collected data is accurate and properly formatted."
|
||||
goal: "Clean and organize the scraped pricing data"
|
||||
tasks:
|
||||
clean_pricing_data:
|
||||
description: "Process the raw scraped data to remove any duplicates and inconsistencies, and convert it into a structured format."
|
||||
expected_output: "Cleaned and organized JSON or CSV file with model pricing data."
|
||||
tools: []
|
||||
data_analyzer:
|
||||
role: "Data Analyzer"
|
||||
backstory: "Data analysis expert focused on deriving actionable insights from structured data."
|
||||
goal: "Analyze the cleaned pricing data to extract insights"
|
||||
tasks:
|
||||
analyze_pricing_data:
|
||||
description: "Analyze the cleaned data to extract trends, patterns, and insights on model pricing."
|
||||
expected_output: "Detailed report summarizing model pricing trends and insights."
|
||||
tools: []
|
||||
dependencies: []
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,66 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
# Example agents_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agents_yaml = """framework: "crewai"
|
||||
topic: "Product Development"
|
||||
roles:
|
||||
market_research_analyst:
|
||||
role: "Market Research Analyst"
|
||||
backstory: "Expert at understanding market demand, target audience, and competition for products like the product. Skilled in developing marketing strategies to reach a wide audience."
|
||||
goal: "Analyze the market demand for the product and suggest marketing strategies using InternetSearchTool."
|
||||
tasks:
|
||||
market_analysis_task:
|
||||
description: "Analyze the market demand for the product. Current month is Jan 2024. Write a report on the ideal customer profile and marketing strategies to reach the widest possible audience. Include at least 10 bullet points addressing key marketing areas. Search the internet using InternetSearchTool."
|
||||
expected_output: "Report on the ideal customer profile and marketing strategies, with at least 10 bullet points addressing key marketing areas."
|
||||
tools:
|
||||
- InternetSearchTool
|
||||
technology_expert:
|
||||
role: "Technology Expert"
|
||||
backstory: "Visionary in current and emerging technological trends, especially in products like the product. Identifies which technologies are best suited for different business models."
|
||||
goal: "Assess technological feasibilities and requirements for producing high-quality the product"
|
||||
tasks:
|
||||
technology_assessment_task:
|
||||
description: "Assess the technological aspects of manufacturing high-quality the product. Write a report detailing necessary technologies and manufacturing approaches. Include at least 10 bullet points on key technological areas."
|
||||
expected_output: "Report detailing necessary technologies and manufacturing approaches, including at least 10 bullet points on key technological areas."
|
||||
business_consultant:
|
||||
role: "Business Development Consultant"
|
||||
backstory: "Seasoned in shaping business strategies for products like the product. Understands scalability and potential revenue streams to ensure long-term sustainability."
|
||||
goal: "Evaluate the business model for the product, focusing on scalability and revenue streams"
|
||||
tasks:
|
||||
business_model_evaluation_task:
|
||||
description: "Summarize the market and technological reports and evaluate the business model for the product. Write a report on the scalability and revenue streams for the product. Include at least 10 bullet points on key business areas. Give Business Plan, Goals, and Timeline for the product launch. Current month is Jan 2024."
|
||||
expected_output: "Comprehensive business model evaluation report including scalability, revenue streams, at least 10 key business areas, Business Plan, Goals, and Timeline for the product launch."
|
||||
"""
|
||||
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content and tools
|
||||
praisonai = PraisonAI(
|
||||
agent_yaml=agents_yaml,
|
||||
tools=[InternetSearchTool] # Just pass the class directly in a list
|
||||
)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,80 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "Children's Storybook Creation"
|
||||
roles:
|
||||
story_outliner:
|
||||
role: "Story Outliner"
|
||||
backstory: "An imaginative creator who lays the foundation of captivating stories for children."
|
||||
goal: "Develop an outline for a children's storybook about Animals, including chapter titles and characters for 5 chapters."
|
||||
tasks:
|
||||
task_outline:
|
||||
description: "Create an outline for the children's storybook about Animals, detailing chapter titles and character descriptions for 5 chapters."
|
||||
expected_output: "A structured outline document containing 5 chapter titles, with detailed character descriptions and the main plot points for each chapter."
|
||||
tools:
|
||||
- InternetSearchTool
|
||||
story_writer:
|
||||
role: "Story Writer"
|
||||
backstory: "A talented storyteller who brings to life the world and characters outlined, crafting engaging and imaginative tales for children."
|
||||
goal: "Write the full content of the story for all 5 chapters, each chapter 100 words, weaving together the narratives and characters outlined."
|
||||
tasks:
|
||||
task_write:
|
||||
description: "Using the outline provided, write the full story content for all chapters, ensuring a cohesive and engaging narrative for children. Each chapter should contain approximately 100 words. Include the title of the story at the top."
|
||||
expected_output: "A complete manuscript of the children's storybook about Animals with 5 chapters, each approximately 100 words, following the provided outline and integrating the characters and plot points into a cohesive narrative."
|
||||
image_generator:
|
||||
role: "Image Generator"
|
||||
backstory: "A creative AI specialized in visual storytelling, bringing each chapter to life through imaginative imagery."
|
||||
goal: "Generate one image per chapter based on the content provided by the story writer. Start with chapter number, chapter content, character details, detailed location information, and detailed items in the location where the activity happens. Generate a total of 5 images one by one. Final output should contain all 5 images in JSON format."
|
||||
tasks:
|
||||
task_image_generate:
|
||||
description: "Generate 5 images that capture the essence of the children's storybook about Animals, aligning with the themes, characters, and narratives outlined in the chapters. Do it one by one."
|
||||
expected_output: "A set of digital images that visually represent each chapter of the children's storybook, incorporating elements from the characters and plot as described in the chapters. The images should be suitable for inclusion in the storybook as illustrations."
|
||||
content_formatter:
|
||||
role: "Content Formatter"
|
||||
backstory: "A meticulous formatter who enhances the readability and presentation of the storybook."
|
||||
goal: "Format the written story content in markdown, including images at the beginning of each chapter."
|
||||
tasks:
|
||||
task_format_content:
|
||||
description: "Format the story content in markdown, including an image at the beginning of each chapter."
|
||||
expected_output: "The entire storybook content formatted in markdown, with each chapter title followed by the corresponding image and the chapter content."
|
||||
output_file: "story.md"
|
||||
markdown_to_pdf_creator:
|
||||
role: "PDF Converter"
|
||||
backstory: "An efficient converter that transforms Markdown files into professionally formatted PDF documents."
|
||||
goal: "Convert the Markdown file to a PDF document. 'story.md' is the markdown file name."
|
||||
tasks:
|
||||
task_markdown_to_pdf:
|
||||
description: "Convert a Markdown file to a PDF document, ensuring the preservation of formatting, structure, and embedded images using the mdpdf library."
|
||||
expected_output: "A PDF file generated from the Markdown input, accurately reflecting the content with proper formatting. The PDF should be ready for sharing or printing."
|
||||
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,51 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "Command Line Operations"
|
||||
|
||||
roles:
|
||||
cli_agent:
|
||||
role: "Software Engineer"
|
||||
backstory: "Expert in command line operations, creating and executing code."
|
||||
goal: "Always use Executor Tool. Ability to perform CLI operations, write programs, and execute using Executor Tool."
|
||||
tools:
|
||||
- "CLITool.execute_cli_command"
|
||||
tasks:
|
||||
cli_task:
|
||||
description: "Identify the operating system."
|
||||
expected_output: "Successfully identifies the OS."
|
||||
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,75 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "News Analysis"
|
||||
|
||||
roles:
|
||||
news_search_agent:
|
||||
role: "News Searcher"
|
||||
backstory: "Expert in analyzing and generating key points from news content for quick updates."
|
||||
goal: "Generate key points for each news article from the latest news."
|
||||
tools:
|
||||
- "SearchNewsDB.news"
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
news_search_task:
|
||||
description: "Search for 'AI 2024' and create key points for each news."
|
||||
expected_output: "Key points for each news article related to 'AI 2024'."
|
||||
writer_agent:
|
||||
role: "Writer"
|
||||
backstory: "Expert in crafting engaging narratives from complex information."
|
||||
goal: "Identify all the topics received. Use the Get News Tool to verify each topic to search. Use the Search tool for detailed exploration of each topic. Summarize the retrieved information in depth for every topic."
|
||||
tools:
|
||||
- "GetNews.news"
|
||||
- "DuckDuckGoSearchRun"
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
writer_task:
|
||||
description: |
|
||||
Go step by step.
|
||||
Step 1: Identify all the topics received.
|
||||
Step 2: Use the Get News Tool to verify each topic by going through one by one.
|
||||
Step 3: Use the Search tool to search for information on each topic one by one.
|
||||
Step 4: Go through every topic and write an in-depth summary of the information retrieved.
|
||||
Don't skip any topic.
|
||||
expected_output: "An in-depth summary of the information retrieved for each topic."
|
||||
|
||||
dependencies:
|
||||
- task: "writer_task"
|
||||
depends_on:
|
||||
- "news_search_task"
|
||||
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,94 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "Job Search Assistance"
|
||||
|
||||
roles:
|
||||
job_searcher_agent:
|
||||
role: "Job Searcher"
|
||||
backstory: "You are actively searching for job opportunities in your field, ready to utilize and expand your skill set in a new role."
|
||||
goal: "Search for jobs in the field of interest, focusing on enhancing relevant skills."
|
||||
tools:
|
||||
- "JobSearchTools.search_jobs"
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
job_search_task:
|
||||
description: |
|
||||
Search for current job openings for the Senior Data Scientist role in New York using the Job Search tool. Find 5 vacant positions in total. Emphasize the key skills required. The tool accepts input in JSON format with the following schema: 'role': '<role>', 'location': '<location>', 'num_results': <number>. Ensure to format the input accordingly.
|
||||
expected_output: "A list of 5 Senior Data Scientist job openings in New York, including key skills required for each position."
|
||||
|
||||
skills_development_agent:
|
||||
role: "Skills Development Advisor"
|
||||
backstory: "As a skills development advisor, you assist job searchers in identifying crucial skills for their target roles and recommend ways to develop these skills."
|
||||
goal: "Identify key skills required for jobs of interest and advise on improving them."
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
skills_highlighting_task:
|
||||
description: |
|
||||
Based on the identified job openings, list the key skills required for each position separately. Provide recommendations on how candidates can acquire or improve these skills through courses, self-study, or practical experience.
|
||||
expected_output: "A detailed list of key skills for each position with recommendations on how to develop them."
|
||||
|
||||
interview_preparation_coach:
|
||||
role: "Interview Preparation Coach"
|
||||
backstory: "Expert in coaching job searchers on successful interview techniques, including mock interviews and feedback."
|
||||
goal: "Enhance interview skills, focusing on common questions, presentation, and communication."
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
interview_preparation_task:
|
||||
description: |
|
||||
Prepare job searchers for interviews by conducting mock interviews and offering feedback on their responses, presentation, and communication skills, for each role separately.
|
||||
expected_output: "Feedback and guidance on interview skills for each role, including common questions and tips on presentation and communication."
|
||||
|
||||
career_advisor:
|
||||
role: "Career Advisor"
|
||||
backstory: "Experienced in guiding candidates through their job search journey, offering personalized advice on career development and application processes."
|
||||
goal: "Assist in resume building, LinkedIn profile optimization, and networking strategies."
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
career_advisory_task:
|
||||
description: |
|
||||
Offer guidance on resume building, optimizing LinkedIn profiles, and effective networking strategies to enhance job application success, for each role separately.
|
||||
expected_output: "Personalized advice on resume enhancement, LinkedIn optimization, and networking strategies for each position."
|
||||
|
||||
dependencies:
|
||||
- task: "skills_highlighting_task"
|
||||
depends_on:
|
||||
- "job_search_task"
|
||||
- task: "interview_preparation_task"
|
||||
depends_on:
|
||||
- "job_search_task"
|
||||
- task: "career_advisory_task"
|
||||
depends_on:
|
||||
- "job_search_task"
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,103 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "AI in healthcare"
|
||||
|
||||
roles:
|
||||
manager:
|
||||
role: "Project Manager"
|
||||
backstory: |
|
||||
With a strategic mindset and a knack for leadership, you excel at guiding teams towards
|
||||
their goals, ensuring projects not only meet but exceed expectations.
|
||||
goal: "Coordinate the project to ensure a seamless integration of research findings into compelling narratives"
|
||||
verbose: true
|
||||
allow_delegation: true
|
||||
max_iter: 10
|
||||
max_rpm: 20
|
||||
tasks:
|
||||
manager_task:
|
||||
description: |
|
||||
Oversee the integration of research findings and narrative development to produce a final comprehensive
|
||||
report on AI in healthcare. Ensure the research is accurately represented and the narrative is engaging and informative.
|
||||
expected_output: "A final comprehensive report that combines the research findings and narrative on AI in healthcare."
|
||||
|
||||
researcher:
|
||||
role: "Senior Researcher"
|
||||
backstory: |
|
||||
Driven by curiosity, you're at the forefront of innovation, eager to explore and share
|
||||
knowledge that could change the world.
|
||||
goal: "Uncover groundbreaking technologies around AI in healthcare"
|
||||
verbose: true
|
||||
tools:
|
||||
- "search_tool"
|
||||
- "ContentTools.read_content"
|
||||
tasks:
|
||||
list_ideas:
|
||||
description: "List of 5 interesting ideas to explore for an article about AI in healthcare."
|
||||
expected_output: "Bullet point list of 5 ideas for an article."
|
||||
async_execution: true
|
||||
list_important_history:
|
||||
description: "Research the history of AI in healthcare and identify the 5 most important events."
|
||||
expected_output: "Bullet point list of 5 important events."
|
||||
async_execution: true
|
||||
|
||||
writer:
|
||||
role: "Writer"
|
||||
backstory: |
|
||||
With a flair for simplifying complex topics, you craft engaging narratives that captivate
|
||||
and educate, bringing new discoveries to light in an accessible manner.
|
||||
goal: "Narrate compelling tech stories around AI in healthcare"
|
||||
verbose: true
|
||||
tools:
|
||||
- "search_tool"
|
||||
- "ContentTools.read_content"
|
||||
tasks:
|
||||
write_article:
|
||||
description: |
|
||||
Compose an insightful article on AI in healthcare, including its history and the latest interesting ideas.
|
||||
expected_output: "A 4-paragraph article about AI in healthcare."
|
||||
context:
|
||||
- "list_ideas"
|
||||
- "list_important_history"
|
||||
callback: "callback_function"
|
||||
|
||||
dependencies:
|
||||
- task: "write_article"
|
||||
depends_on:
|
||||
- "list_ideas"
|
||||
- "list_important_history"
|
||||
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,69 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """framework: "crewai"
|
||||
topic: "AI Advancements in 2024"
|
||||
roles:
|
||||
researcher:
|
||||
role: "Senior Research Analyst"
|
||||
backstory: |
|
||||
You are an expert at a technology research group, skilled in identifying trends and analyzing complex data.
|
||||
goal: "Uncover cutting-edge developments in AI and data science"
|
||||
verbose: true
|
||||
allow_delegation: false
|
||||
tools:
|
||||
- "search_tool"
|
||||
tasks:
|
||||
task1:
|
||||
description: |
|
||||
Analyze 2024's AI advancements. Find major trends, new technologies, and their effects. Provide a detailed report.
|
||||
expected_output: "A detailed report on major AI trends, new technologies, and their effects in 2024."
|
||||
writer:
|
||||
role: "Tech Content Strategist"
|
||||
backstory: |
|
||||
You are a content strategist known for making complex tech topics interesting and easy to understand.
|
||||
goal: "Craft compelling content on tech advancements"
|
||||
verbose: true
|
||||
allow_delegation: true
|
||||
tasks:
|
||||
task2:
|
||||
description: |
|
||||
Create a blog post about major AI advancements using your insights. Make it interesting, clear, and suited for tech enthusiasts. It should be at least 4 paragraphs long.
|
||||
expected_output: "An engaging blog post of at least 4 paragraphs about major AI advancements, suitable for tech enthusiasts."
|
||||
dependencies:
|
||||
- task: "task2"
|
||||
depends_on:
|
||||
- "task1"
|
||||
"""
|
||||
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,83 +0,0 @@
|
||||
# tools.py
|
||||
import requests
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class TranslatorTool(BaseTool):
|
||||
name: str = "Translator Tool"
|
||||
description: str = "Translate text from one language to another."
|
||||
|
||||
def _run(self, q: str, target: str):
|
||||
url = "http://127.0.0.1:5000/translate"
|
||||
payload = {
|
||||
"q": q,
|
||||
"source": "auto", # Automatically detect the source language
|
||||
"target": target
|
||||
}
|
||||
headers = {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
response = requests.post(url, json=payload, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
try:
|
||||
data = response.json()
|
||||
return data
|
||||
except requests.exceptions.JSONDecodeError:
|
||||
return "Failed to decode JSON from the response."
|
||||
else:
|
||||
return f"Request failed with status code: {response.status_code}"
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "Writing an article about AI"
|
||||
roles:
|
||||
article_writer:
|
||||
role: "Article Writer"
|
||||
backstory: "Experienced writer with a deep understanding of artificial intelligence and technology trends."
|
||||
goal: "Write an informative and engaging article about AI."
|
||||
tasks:
|
||||
write_article:
|
||||
description: "Write a comprehensive article about the latest developments and implications of AI."
|
||||
expected_output: "A well-written article on AI in English."
|
||||
french_translator:
|
||||
role: "Translator"
|
||||
backstory: "Fluent in French with expertise in translating technical and non-technical content accurately."
|
||||
goal: "Translate the AI article into French."
|
||||
tasks:
|
||||
translate_to_french:
|
||||
description: "Translate the English article on AI into French."
|
||||
expected_output: "The AI article translated into French."
|
||||
tools:
|
||||
- "TranslatorTool"
|
||||
german_translator:
|
||||
role: "Translator"
|
||||
backstory: "Proficient in German with a strong background in technical translation."
|
||||
goal: "Translate the AI article into German."
|
||||
tasks:
|
||||
translate_to_german:
|
||||
description: "Translate the English article on AI into German."
|
||||
expected_output: "The AI article translated into German."
|
||||
tools:
|
||||
- "TranslatorTool"
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,126 +0,0 @@
|
||||
# tools.py
|
||||
from mem0 import Memory
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class AddMemoryTool(BaseTool):
|
||||
name: str = "Add Memory Tool"
|
||||
description: str = ("This tool allows storing a new memory with user ID and optional metadata.\n"
|
||||
"Example:\n"
|
||||
" - Input: text='I am working on improving my tennis skills. Suggest some online courses.', user_id='alice', metadata={'category': 'hobbies'}\n"
|
||||
" - Output: Memory added with summary 'Improving her tennis skills. Looking for online suggestions.'")
|
||||
|
||||
def _run(self, text: str, user_id: str, metadata: dict = None):
|
||||
m = Memory()
|
||||
result = m.add(text, user_id=user_id, metadata=metadata)
|
||||
return result
|
||||
|
||||
class GetAllMemoriesTool(BaseTool):
|
||||
name: str = "Get All Memories Tool"
|
||||
description: str = ("This tool retrieves all stored memories.\n"
|
||||
"Example:\n"
|
||||
" - Input: action='get_all'\n"
|
||||
" - Output: List of all stored memories.")
|
||||
|
||||
def _run(self):
|
||||
m = Memory()
|
||||
result = m.get_all()
|
||||
return result
|
||||
|
||||
class SearchMemoryTool(BaseTool):
|
||||
name: str = "Search Memory Tool"
|
||||
description: str = ("This tool searches for specific memories based on a query and user ID.\n"
|
||||
"Example:\n"
|
||||
" - Input: query='What are Alice's hobbies?', user_id='alice'\n"
|
||||
" - Output: Search results related to Alice's hobbies.")
|
||||
|
||||
def _run(self, query: str, user_id: str):
|
||||
m = Memory()
|
||||
result = m.search(query=query, user_id=user_id)
|
||||
return result
|
||||
|
||||
class UpdateMemoryTool(BaseTool):
|
||||
name: str = "Update Memory Tool"
|
||||
description: str = ("This tool updates an existing memory by memory ID and new data.\n"
|
||||
"Example:\n"
|
||||
" - Input: memory_id='cb032b42-0703-4b9c-954d-77c36abdd660', data='Likes to play tennis on weekends'\n"
|
||||
" - Output: Memory updated to 'Likes to play tennis on weekends.'")
|
||||
|
||||
def _run(self, memory_id: str, data: str):
|
||||
m = Memory()
|
||||
result = m.update(memory_id=memory_id, data=data)
|
||||
return result
|
||||
|
||||
class MemoryHistoryTool(BaseTool):
|
||||
name: str = "Memory History Tool"
|
||||
description: str = ("This tool gets the history of changes made to a specific memory by memory ID.\n"
|
||||
"Example:\n"
|
||||
" - Input: memory_id='cb032b42-0703-4b9c-954d-77c36abdd660'\n"
|
||||
" - Output: History of the specified memory.")
|
||||
|
||||
def _run(self, memory_id: str):
|
||||
m = Memory()
|
||||
result = m.history(memory_id=memory_id)
|
||||
return result
|
||||
|
||||
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
# Example agent_yaml content
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from praisonai import PraisonAI
|
||||
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "personal memory management"
|
||||
roles:
|
||||
data_analyst:
|
||||
role: "Data Analyst"
|
||||
backstory: "Skilled in analyzing data to find trends and insights."
|
||||
goal: "Analyze the data to provide useful insights and recommendations."
|
||||
tasks:
|
||||
research_ai_news:
|
||||
description: "Analyze the latest AI news from July 2024 and trends to provide insights and recommendations."
|
||||
expected_output: "Report with insights on the latest AI trends and personalized recommendations."
|
||||
tools:
|
||||
- "InternetSearchTool"
|
||||
user_support:
|
||||
role: "User Support"
|
||||
backstory: "Expert in assisting users with queries and issues related to memory management."
|
||||
goal: "Provide support to users for adding information to memories."
|
||||
tasks:
|
||||
support_users:
|
||||
description: "Assist users in adding information to memories."
|
||||
expected_output: "User queries resolved and memories managed effectively."
|
||||
tools:
|
||||
- "AddMemoryTool"
|
||||
- "GetAllMemoriesTool"
|
||||
- "SearchMemoryTool"
|
||||
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Add OPENAI_API_KEY Secrets to Google Colab on the Left Hand Side 🔑 or Enter Manually Below
|
||||
# os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY') or "ENTER OPENAI_API_KEY HERE"
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
@@ -1,49 +0,0 @@
|
||||
```markdown
|
||||
# The Secret Meeting Spot
|
||||
|
||||

|
||||
|
||||
## Chapter 1: The Secret Meeting Spot
|
||||
|
||||
Luna the Wise Owl had called for a secret meeting in the heart of the Enchanted Forest. Perched on the branch of the ancient oak tree, she awaited her friends with a mysterious map clutched in her talons. Max the Brave Squirrel scampered up to the tree, his eyes gleaming with excitement. Ella the Curious Fawn approached, her gaze fixed on the map that promised an adventure like no other. The forest around them was alive with magical flora, casting a soft, mystical glow that hinted at the wonders to come.
|
||||
|
||||
---
|
||||
|
||||
# The Mysterious Riverbank
|
||||
|
||||

|
||||
|
||||
## Chapter 2: The Mysterious Riverbank
|
||||
|
||||
The group made their way to the bustling riverbank, where Benny the Playful Beaver was hard at work constructing a sturdy wooden bridge. Luna, Max, Ella, and Benny crossed the bridge together, the river sparkling beneath them. As they journeyed along the riverbank, they noticed strange markings on the trees, hinting at the presence of others. The air was filled with an atmosphere of mystery and excitement, urging them forward on their quest.
|
||||
|
||||
---
|
||||
|
||||
# The Hidden Glade of Whispers
|
||||
|
||||

|
||||
|
||||
## Chapter 3: The Hidden Glade of Whispers
|
||||
|
||||
In the heart of the forest lay the Hidden Glade of Whispers, a place where the wind itself shared secrets. Mia the Shy Rabbit joined Luna, Max, Ella, and Benny as they gathered to decipher the whispers. Sunlight filtered through the trees, casting an ethereal light that enveloped the glade in soft colors. It was here that the bond between the friends grew stronger, their shared purpose guiding them as they unraveled the riddle together.
|
||||
|
||||
---
|
||||
|
||||
# The Cavern of Echoes
|
||||
|
||||

|
||||
|
||||
## Chapter 4: The Cavern of Echoes
|
||||
|
||||
The journey led them to the Cavern of Echoes, a dark and mysterious place where Oliver the Inventive Raccoon's gadgets illuminated their path. Together, Luna, Max, Ella, Benny, and Mia navigated the maze-like tunnels, each echo playing tricks on their minds. Swirling shadows and light portrayed the challenges they faced, their teamwork and trust shining through as they discovered a crucial clue that would lead them to their goal.
|
||||
|
||||
---
|
||||
|
||||
# The Treasure of Friendship
|
||||
|
||||

|
||||
|
||||
## Chapter 5: The Treasure of Friendship
|
||||
|
||||
Finally, the friends emerged into a serene meadow bathed in the warm glow of the setting sun. There, they uncovered a chest filled with seeds and a heartfelt message. United and joyful, they planted the seeds together, a symbol of growth and new adventures on the horizon. The scene captured the essence of friendship, the realization of their true treasure, and the promise of nature's beauty and more adventures to come.
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def run_terminal_command(command: str):
|
||||
"""
|
||||
Run a terminal command and return its output.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
print(f"Command output: {result}")
|
||||
return {"stdout": result.stdout, "stderr": result.stderr}
|
||||
except subprocess.CalledProcessError as e:
|
||||
return {"error": str(e), "stdout": e.stdout, "stderr": e.stderr}
|
||||
|
||||
def save_to_file(file_path: str, content: str):
|
||||
"""
|
||||
Save the given content to the specified file path. Create the folder/file if it doesn't exist.
|
||||
"""
|
||||
# Ensure the directory exists
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
# Write the content to the file
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(content)
|
||||
|
||||
return file_path
|
||||
|
||||
# Create System Operations Agent
|
||||
system_ops_agent = Agent(
|
||||
name="SystemOps",
|
||||
role="System Operations Specialist",
|
||||
goal="Execute and manage complex system operations and commands",
|
||||
backstory="""You are an expert system administrator with deep knowledge of Unix/Linux systems.
|
||||
You excel at running complex system commands, managing processes, and handling system operations.
|
||||
You always validate commands before execution and ensure they are safe to run.""",
|
||||
min_reflect=6,
|
||||
max_reflect=10,
|
||||
tools=[run_terminal_command, save_to_file],
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
# Create a complex task that tests various system operations
|
||||
task = Task(
|
||||
name="system_analysis_task",
|
||||
description="""Perform a comprehensive system analysis by executing the following operations in sequence:
|
||||
1. Get system information (OS, kernel version)
|
||||
2. List 5 running processes and sort them by CPU usage
|
||||
3. Check disk space usage and list directories over 1GB
|
||||
4. Display current system load and memory usage
|
||||
5. List 5 network connections
|
||||
6. Create a summary report with all findings in a text file called system_report.txt
|
||||
|
||||
Do it step by step. One task at a time.
|
||||
Save only the Summary report in the file.
|
||||
Use appropriate commands for each step and ensure proper error handling.""",
|
||||
expected_output="A comprehensive system report containing all requested information saved in system_report.txt",
|
||||
agent=system_ops_agent,
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[system_ops_agent],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
@@ -0,0 +1,46 @@
|
||||
framework: praisonai
|
||||
topic: crawl and extract all data from each url from this page https://news.ycombinator.com/
|
||||
roles:
|
||||
web_scraper:
|
||||
backstory: An expert in data extraction from websites, adept at navigating and
|
||||
retrieving detailed information.
|
||||
goal: Extract URLs from the source page
|
||||
role: Web Scraper
|
||||
output_file: urls.txt
|
||||
tasks:
|
||||
url_extraction:
|
||||
description: Use the code_interpret run python code to extract all URLs from the page located
|
||||
at https://news.ycombinator.com/.
|
||||
expected_output: A list of URLs extracted from the source page.
|
||||
tools:
|
||||
- 'code_interpret'
|
||||
url_data_extractor:
|
||||
backstory: Specializes in crawling websites to gather comprehensive data, ensuring
|
||||
nothing is missed from each link.
|
||||
goal: Crawl each URL for data extraction
|
||||
role: URL Data Extractor
|
||||
context:
|
||||
- web_scraper
|
||||
tasks:
|
||||
data_extraction:
|
||||
description: Crawl each URL provided by the Web Scraper and extract all pertinent
|
||||
data using the code_interpret to run python code.
|
||||
expected_output: Raw data collected from each crawled URL.
|
||||
tools:
|
||||
- 'code_interpret'
|
||||
data_organizer:
|
||||
backstory: Known for keen attention to detail, capable of structuring vast amounts
|
||||
of information into usable formats efficiently.
|
||||
goal: Organize extracted data into a structured format
|
||||
role: Data Organizer
|
||||
context:
|
||||
- url_data_extractor
|
||||
tasks:
|
||||
data_structuring:
|
||||
description: Organize the raw data received from the URL Data Extractor into
|
||||
a structured JSON format.
|
||||
expected_output: A JSON file containing structured data from all extracted
|
||||
URLs.
|
||||
tools:
|
||||
- 'code_interpret'
|
||||
dependencies: []
|
||||
@@ -0,0 +1,94 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs
|
||||
import json
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
def code_interpret(code: str):
|
||||
"""
|
||||
A function to demonstrate running Python code dynamically using e2b_code_interpreter.
|
||||
"""
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
|
||||
# 1) Create Agents
|
||||
web_scraper_agent = Agent(
|
||||
name="WebScraper",
|
||||
role="Web Scraper",
|
||||
goal="Extract URLs from https://quotes.toscrape.com/",
|
||||
backstory="An expert in data extraction from websites, adept at navigating and retrieving detailed information.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
url_data_extractor_agent = Agent(
|
||||
name="URLDataExtractor",
|
||||
role="URL Data Extractor",
|
||||
goal="Crawl each URL for data extraction",
|
||||
backstory="Specializes in crawling websites to gather comprehensive data, ensuring nothing is missed from each link.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
blog_writer_agent = Agent(
|
||||
name="BlogWriter",
|
||||
role="Creative Content Writer",
|
||||
goal="Create engaging and insightful blog posts from provided data",
|
||||
backstory="An experienced content creator and storyteller with a knack for weaving compelling narratives. Skilled at analyzing quotes and creating meaningful connections that resonate with readers.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# 2) Create Tasks
|
||||
task_url_extraction = Task(
|
||||
name="url_extraction_task",
|
||||
description="""Use code_interpret to run Python code that fetches https://quotes.toscrape.com/
|
||||
and extracts 5 URLs from the page, then outputs them as a list. Only first 5 urls""",
|
||||
expected_output="A list of URLs extracted from the source page.",
|
||||
agent=web_scraper_agent,
|
||||
output_file="urls.txt"
|
||||
)
|
||||
|
||||
task_data_extraction = Task(
|
||||
name="data_extraction_task",
|
||||
description="""Take the URLs from url_extraction_task, crawl each URL and extract all pertinent
|
||||
data using code_interpret to run Python code, then output raw txt, not the html.""",
|
||||
expected_output="Raw data collected from each crawled URL.",
|
||||
agent=url_data_extractor_agent,
|
||||
context=[task_url_extraction]
|
||||
)
|
||||
|
||||
blog_writing_task = Task(
|
||||
name="blog_writing_task",
|
||||
description="""Write an engaging blog post using the extracted quotes data. The blog post should:
|
||||
1. Have a catchy title
|
||||
2. Include relevant quotes from the data
|
||||
3. Provide commentary and insights about the quotes
|
||||
4. Be well-structured with introduction, body, and conclusion
|
||||
5. Be approximately 500 words long""",
|
||||
expected_output="A well-written blog post incorporating the extracted quotes with analysis",
|
||||
agent=blog_writer_agent,
|
||||
context=[task_data_extraction],
|
||||
output_file="blog_post.txt"
|
||||
)
|
||||
|
||||
# 3) Create and run Agents manager
|
||||
agents_manager = PraisonAIAgents(
|
||||
agents=[web_scraper_agent, url_data_extractor_agent, blog_writer_agent],
|
||||
tasks=[task_url_extraction, task_data_extraction, blog_writing_task],
|
||||
verbose=True,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents_manager.start()
|
||||
@@ -0,0 +1,78 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs
|
||||
import json, os
|
||||
from e2b_code_interpreter import Sandbox
|
||||
import subprocess
|
||||
|
||||
def code_interpret(code: str):
|
||||
"""
|
||||
A function to demonstrate running Python code dynamically using e2b_code_interpreter.
|
||||
"""
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
|
||||
def save_to_file(file_path: str, content: str):
|
||||
"""
|
||||
Save the given content to the specified file path. Create the folder/file if it doesn't exist.
|
||||
"""
|
||||
# Ensure the directory exists
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
# Write the content to the file
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(content)
|
||||
|
||||
return file_path
|
||||
|
||||
def run_terminal_command(command: str):
|
||||
"""
|
||||
Run a terminal command and return its output.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
print(f"Command output: {result}")
|
||||
return {"stdout": result.stdout, "stderr": result.stderr}
|
||||
except subprocess.CalledProcessError as e:
|
||||
return {"error": str(e), "stdout": e.stdout, "stderr": e.stderr}
|
||||
|
||||
|
||||
# 1) Create Agents
|
||||
web_scraper_agent = Agent(
|
||||
name="WebScraper",
|
||||
role="Web Scraper",
|
||||
goal="Extract URLs from https://news.ycombinator.com/",
|
||||
backstory="An expert in data extraction from websites, adept at navigating and retrieving detailed information and saving it to a file. and just check if the file is created using run_terminal_command tool",
|
||||
min_reflect=3,
|
||||
max_reflect=5,
|
||||
tools=[code_interpret, save_to_file, run_terminal_command],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
task = Task(
|
||||
name="url_extraction_task",
|
||||
description="""Use code_interpret to run Python code that fetches https://news.ycombinator.com/
|
||||
and extracts first 20 URLs from the page, with full path, then outputs them in a txt file.""",
|
||||
expected_output="A list of URLs extracted from the source page in a txt file.",
|
||||
agent=web_scraper_agent,
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[web_scraper_agent],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
|
||||
print(result)
|
||||
@@ -0,0 +1,24 @@
|
||||
import json
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
def code_interpret(code: str):
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec = Sandbox().run_code(code)
|
||||
|
||||
if exec.error:
|
||||
print("[Code Interpreter error]", exec.error)
|
||||
return {"error": str(exec.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec.results:
|
||||
# Ensure each result is a list or a simple Python type
|
||||
if hasattr(result, '__iter__'):
|
||||
result_list = list(result) # Convert Result to list
|
||||
results.extend(result_list)
|
||||
else:
|
||||
results.append(str(result)) # Fall back to string
|
||||
|
||||
logs = {"stdout": list(exec.logs.stdout), "stderr": list(exec.logs.stderr)}
|
||||
|
||||
# Now everything is JSON-serialisable
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
@@ -1,72 +0,0 @@
|
||||
# tools.py
|
||||
from duckduckgo_search import DDGS
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class InternetSearchTool(BaseTool):
|
||||
name: str = "InternetSearchTool"
|
||||
description: str = "Search Internet for relevant information based on a query or latest news"
|
||||
|
||||
def _run(self, query: str):
|
||||
ddgs = DDGS()
|
||||
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
|
||||
return results
|
||||
|
||||
from langchain_community.tools.pubmed.tool import PubmedQueryRun
|
||||
from langchain_community.tools.reddit_search.tool import RedditSearchRun
|
||||
# pip install tavily-python
|
||||
from langchain_community.utilities.tavily_search import TavilySearchAPIWrapper
|
||||
from langchain_community.utilities.you import YouSearchAPIWrapper
|
||||
# pip install youtube_search
|
||||
from langchain_community.tools import YouTubeSearchTool
|
||||
# pip install wikipedia
|
||||
from langchain_community.utilities import WikipediaAPIWrapper
|
||||
|
||||
class TavilyTool(BaseTool):
|
||||
name: str = "TavilyTool"
|
||||
description: str = "Search Tavily for relevant information based on a query."
|
||||
|
||||
def _run(self, query: str):
|
||||
api_wrapper = TavilySearchAPIWrapper()
|
||||
results = api_wrapper.results(query=query, max_results=5)
|
||||
return results
|
||||
|
||||
class YouSearchTool(BaseTool):
|
||||
name: str = "You Search Tool"
|
||||
description: str = "Search You.com for relevant information based on a query."
|
||||
|
||||
def _run(self, query: str):
|
||||
api_wrapper = YouSearchAPIWrapper()
|
||||
results = api_wrapper.results(query=query, max_results=5)
|
||||
return results
|
||||
|
||||
class WikipediaSearchTool(BaseTool):
|
||||
name: str = "WikipediaSearchTool"
|
||||
description: str = "Search Wikipedia for relevant information based on a query."
|
||||
|
||||
def _run(self, query: str):
|
||||
api_wrapper = WikipediaAPIWrapper(top_k_results=4, doc_content_chars_max=100)
|
||||
results = api_wrapper.load(query=query)
|
||||
return results
|
||||
|
||||
# pip install open-interpreter
|
||||
from interpreter import interpreter
|
||||
from praisonai_tools import BaseTool
|
||||
|
||||
class OpenInterpreterTool(BaseTool):
|
||||
name: str = "Open Interpreter Tool"
|
||||
description: str = "Use Open Interpreter configured to create and execute code based on natural language commands."
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
interpreter.auto_run = True
|
||||
|
||||
def _run(self, code: str):
|
||||
result = interpreter.chat(code)
|
||||
return result
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
tool = OpenInterpreterTool()
|
||||
code = "Plot AAPL and META's normalized stock prices"
|
||||
output = tool._run(code)
|
||||
print(output)
|
||||
@@ -0,0 +1,21 @@
|
||||
services:
|
||||
ui:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.ui
|
||||
volumes:
|
||||
- .:/app
|
||||
ports:
|
||||
- "8082:8082"
|
||||
environment:
|
||||
FLASK_ENV: development
|
||||
CHAINLIT_PORT: "8082"
|
||||
CHAINLIT_HOST: "0.0.0.0"
|
||||
OPENAI_API_KEY: ${OPENAI_API_KEY}
|
||||
CHAINLIT_AUTH_SECRET: ${CHAINLIT_AUTH_SECRET}
|
||||
command: praisonai ui --host 0.0.0.0
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8082"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: 'API Reference'
|
||||
description: 'PraisonAI API documentation with framework-specific details'
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
# API Reference
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
# API Reference
|
||||
---
|
||||
title: "API Reference"
|
||||
description: "Complete API reference for PraisonAI, including core modules, installation options, and framework-specific features"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
## Core Modules
|
||||
|
||||
@@ -110,7 +110,7 @@ Loads environment variables from .env file or system and sets them.</p>
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.14 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.26 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
title: "Agent Module"
|
||||
description: "Documentation for the praisonaiagents.agent.agent module"
|
||||
icon: "user"
|
||||
---
|
||||
|
||||
# Module praisonaiagents.agent.agent
|
||||
|
||||
## Classes
|
||||
|
||||
### Agent
|
||||
The main class representing an AI agent with specific role, goal, and capabilities.
|
||||
|
||||
#### Parameters
|
||||
- `name: str` - Name of the agent
|
||||
- `role: str` - Role of the agent
|
||||
- `goal: str` - Goal the agent aims to achieve
|
||||
- `backstory: str` - Background story of the agent
|
||||
- `llm: str | Any | None = 'gpt-4o'` - Language model to use
|
||||
- `tools: List[Any] | None = None` - List of tools available to the agent
|
||||
- `function_calling_llm: Any | None = None` - LLM for function calling
|
||||
- `max_iter: int = 20` - Maximum iterations
|
||||
- `max_rpm: int | None = None` - Maximum requests per minute
|
||||
- `max_execution_time: int | None = None` - Maximum execution time
|
||||
- `memory: bool = True` - Enable memory
|
||||
- `verbose: bool = True` - Enable verbose output
|
||||
- `allow_delegation: bool = False` - Allow task delegation
|
||||
- `step_callback: Any | None = None` - Callback for each step
|
||||
- `cache: bool = True` - Enable caching
|
||||
- `system_template: str | None = None` - System prompt template
|
||||
- `prompt_template: str | None = None` - Prompt template
|
||||
- `response_template: str | None = None` - Response template
|
||||
- `allow_code_execution: bool | None = False` - Allow code execution
|
||||
- `max_retry_limit: int = 2` - Maximum retry attempts
|
||||
- `respect_context_window: bool = True` - Respect context window size
|
||||
- `code_execution_mode: Literal['safe', 'unsafe'] = 'safe'` - Code execution mode
|
||||
- `embedder_config: Dict[str, Any] | None = None` - Embedder configuration
|
||||
- `knowledge_sources: List[Any] | None = None` - Knowledge sources
|
||||
- `use_system_prompt: bool | None = True` - Use system prompt
|
||||
- `markdown: bool = True` - Enable markdown
|
||||
- `self_reflect: bool = True` - Enable self reflection
|
||||
- `max_reflect: int = 3` - Maximum reflections
|
||||
- `min_reflect: int = 1` - Minimum reflections
|
||||
- `reflect_llm: str | None = None` - LLM for reflection
|
||||
|
||||
#### Methods
|
||||
- `chat(self, prompt, temperature=0.2, tools=None, output_json=None)` - Chat with the agent
|
||||
- `achat(self, prompt, temperature=0.2, tools=None, output_json=None)` - Async version of chat method
|
||||
- `clean_json_output(self, output: str) → str` - Clean and extract JSON from response text
|
||||
- `clear_history(self)` - Clear chat history
|
||||
- `execute_tool(self, function_name, arguments)` - Execute a tool dynamically based on the function name and arguments
|
||||
- `_achat_completion(self, response, tools)` - Async version of _chat_completion method
|
||||
|
||||
#### Async Support
|
||||
The Agent class provides async support through the following methods:
|
||||
|
||||
- `achat`: Async version of the chat method for non-blocking communication
|
||||
- `_achat_completion`: Internal async method for handling chat completions
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
async def main():
|
||||
agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Async Specialist",
|
||||
goal="Handle async operations",
|
||||
backstory="Expert in async processing"
|
||||
)
|
||||
|
||||
# Use async chat
|
||||
result = await agent.achat(
|
||||
prompt="Your prompt here",
|
||||
tools=your_tools,
|
||||
output_json=your_schema
|
||||
)
|
||||
print(result)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
title: "Agents Module"
|
||||
description: "Documentation for the praisonaiagents.agents.agents module"
|
||||
icon: "users"
|
||||
---
|
||||
|
||||
# Module praisonaiagents.agents.agents
|
||||
|
||||
## Functions
|
||||
|
||||
### encode_file_to_base64(file_path: str) → str
|
||||
Base64-encode a file.
|
||||
|
||||
### process_video(video_path: str, seconds_per_frame=2)
|
||||
Split video into frames (base64-encoded).
|
||||
|
||||
## Classes
|
||||
|
||||
### LoopItems
|
||||
A Pydantic model for handling loop items.
|
||||
|
||||
#### Class Variables
|
||||
- `items: List[Any]` - List of items to loop through
|
||||
- `model_config` - Model configuration
|
||||
|
||||
### PraisonAIAgents
|
||||
The main class for managing agents and tasks execution.
|
||||
|
||||
#### Parameters
|
||||
- `agents: List[Agent]` - List of agents
|
||||
- `tasks: List[Task]` - List of tasks
|
||||
- `verbose: int = 0` - Verbosity level
|
||||
- `completion_checker: Optional[Callable] = None` - Custom completion checker
|
||||
- `max_retries: int = 5` - Maximum retry attempts
|
||||
- `process: str = "sequential"` - Process type (sequential, workflow, hierarchical)
|
||||
- `manager_llm: Optional[str] = None` - Language model for manager agent
|
||||
|
||||
#### Methods
|
||||
- `add_task(self, task)` - Add a task to the crew
|
||||
- `clean_json_output(self, output: str) → str` - Clean JSON output
|
||||
- `clear_state(self) → None` - Clear all state values
|
||||
- `default_completion_checker(self, task, agent_output)` - Default completion checker
|
||||
- `execute_task(self, task_id)` - Execute a specific task
|
||||
- `get_agent_details(self, agent_name)` - Get agent details
|
||||
- `get_all_tasks_status(self)` - Get status of all tasks
|
||||
- `get_state(self, key: str, default: Any = None) → Any` - Get a state value
|
||||
- `get_task_details(self, task_id)` - Get task details
|
||||
- `get_task_result(self, task_id)` - Get task result
|
||||
- `get_task_status(self, task_id)` - Get task status
|
||||
- `run_all_tasks(self)` - Execute tasks based on execution mode
|
||||
- `run_task(self, task_id)` - Run a specific task
|
||||
- `save_output_to_file(self, task, task_output)` - Save task output to file
|
||||
- `set_state(self, key: str, value: Any) → None` - Set a state value
|
||||
- `start(self)` - Start the crew execution
|
||||
- `update_state(self, updates: Dict) → None` - Update multiple state values
|
||||
|
||||
#### Async Methods
|
||||
- `astart(self)` - Async version of start method
|
||||
- `aexecute_task(self, task_id)` - Async version of execute_task
|
||||
- `arun_task(self, task_id)` - Async version of run_task
|
||||
- `arun_all_tasks(self)` - Async version of run_all_tasks
|
||||
|
||||
#### Async Support
|
||||
The PraisonAIAgents class provides comprehensive async support through the following methods:
|
||||
|
||||
```python
|
||||
class PraisonAIAgents:
|
||||
async def astart(self):
|
||||
"""Async version of start method"""
|
||||
await self.arun_all_tasks()
|
||||
return {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": self.get_task_results()
|
||||
}
|
||||
|
||||
async def aexecute_task(self, task_id):
|
||||
"""Async version of execute_task method"""
|
||||
# Async task execution implementation
|
||||
|
||||
async def arun_task(self, task_id):
|
||||
"""Async version of run_task method"""
|
||||
# Async task running with retries
|
||||
|
||||
async def arun_all_tasks(self):
|
||||
"""Async version of run_all_tasks method"""
|
||||
# Async execution of all tasks
|
||||
```
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
async def main():
|
||||
# Initialize agents and tasks
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent1, async_agent2],
|
||||
tasks=[async_task1, async_task2],
|
||||
process="workflow"
|
||||
)
|
||||
|
||||
# Start async execution
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the async workflow
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
#### Async Features
|
||||
- Full async/await support
|
||||
- Parallel task execution
|
||||
- Non-blocking operations
|
||||
- Efficient resource utilization
|
||||
- Mixed sync/async task handling
|
||||
- Async process management
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "API Reference"
|
||||
description: "Praison AI Agents - SDK Documentation"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agent" icon="user" href="/api/praisonaiagents/agent/agent">
|
||||
Documentation for individual AI agents and their capabilities
|
||||
</Card>
|
||||
<Card title="Agents" icon="users" href="/api/praisonaiagents/agents/agents">
|
||||
Documentation for managing multiple agents and their interactions
|
||||
</Card>
|
||||
<Card title="Task" icon="list-check" href="/api/praisonaiagents/task/task">
|
||||
Documentation for defining and managing tasks
|
||||
</Card>
|
||||
<Card title="Process" icon="diagram-project" href="/api/praisonaiagents/process/process">
|
||||
Documentation for handling task execution flows
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
# Module praisonaiagents
|
||||
|
||||
## Sub-modules
|
||||
* praisonaiagents.agent - Agent module for defining individual AI agents
|
||||
* praisonaiagents.agents - Agents module for managing multiple agents
|
||||
* praisonaiagents.task - Task module for defining and managing tasks
|
||||
* praisonaiagents.process - Process module for handling task execution flows
|
||||
* praisonaiagents.main - Main module containing utility functions
|
||||
|
||||
## Functions
|
||||
|
||||
### clean_triple_backticks(text: str) → str
|
||||
Clean triple backticks from text output.
|
||||
|
||||
### display_error(message: str, console=None)
|
||||
Display error messages in the console.
|
||||
|
||||
### display_generating(content: str = '', start_time: float | None = None)
|
||||
Display generation status with optional timing information.
|
||||
|
||||
### display_instruction(message: str, console=None)
|
||||
Display instruction messages in the console.
|
||||
|
||||
### display_interaction(message, response, markdown=True, generation_time=None, console=None)
|
||||
Display interaction between user and agent.
|
||||
|
||||
### display_self_reflection(message: str, console=None)
|
||||
Display agent self-reflection messages.
|
||||
|
||||
### display_tool_call(message: str, console=None)
|
||||
Display tool call messages.
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "Process Module"
|
||||
description: "Documentation for the praisonaiagents.process.process module"
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
# Module praisonaiagents.process.process
|
||||
|
||||
## Classes
|
||||
|
||||
### Process
|
||||
The main class for handling task execution processes in different modes (sequential, hierarchical, workflow).
|
||||
|
||||
#### Parameters
|
||||
- `tasks: Dict[str, Task]` - Dictionary of tasks to be executed
|
||||
- `agents: List[Agent]` - List of available agents
|
||||
- `manager_llm: Optional[str] = None` - Language model for manager agent in hierarchical process
|
||||
- `verbose: bool = False` - Enable verbose logging
|
||||
|
||||
#### Methods
|
||||
- `workflow(self)` - Execute tasks in a workflow pattern with support for loops and conditions
|
||||
- `sequential(self)` - Execute tasks in sequential order
|
||||
- `hierarchical(self)` - Execute tasks in hierarchical order with a manager agent
|
||||
|
||||
#### Async Methods
|
||||
- `aworkflow(self) -> AsyncGenerator[str, None]` - Async version of workflow process
|
||||
- `asequential(self) -> AsyncGenerator[str, None]` - Async version of sequential process
|
||||
- `ahierarchical(self) -> AsyncGenerator[str, None]` - Async version of hierarchical process
|
||||
|
||||
#### Async Process Support
|
||||
Each process type has an async counterpart that supports non-blocking execution:
|
||||
|
||||
```python
|
||||
class Process:
|
||||
async def aworkflow(self):
|
||||
"""Async workflow process execution"""
|
||||
# Async workflow implementation
|
||||
|
||||
async def asequential(self):
|
||||
"""Async sequential process execution"""
|
||||
# Async sequential implementation
|
||||
|
||||
async def ahierarchical(self):
|
||||
"""Async hierarchical process execution"""
|
||||
# Async hierarchical implementation
|
||||
```
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
# Create process instance
|
||||
process = Process(tasks=tasks, agents=agents)
|
||||
|
||||
# Use async workflow
|
||||
async for task_id in process.aworkflow():
|
||||
# Handle task execution
|
||||
if tasks[task_id].async_execution:
|
||||
await handle_async_task(task_id)
|
||||
else:
|
||||
handle_sync_task(task_id)
|
||||
```
|
||||
|
||||
#### Async Process Features
|
||||
- Non-blocking task execution
|
||||
- Parallel task processing
|
||||
- Mixed sync/async task support
|
||||
- Efficient resource utilization
|
||||
- Async manager coordination (hierarchical)
|
||||
- Dynamic task scheduling (workflow)
|
||||
|
||||
### LoopItems
|
||||
A Pydantic model for handling loop data in workflow process.
|
||||
|
||||
#### Parameters
|
||||
- `items: List[Any]` - List of items to be processed in a loop
|
||||
|
||||
## Process Types
|
||||
|
||||
### Sequential Process
|
||||
- Tasks are executed one after another in a linear fashion
|
||||
- Each task is completed before moving to the next one
|
||||
- Simplest form of task execution
|
||||
|
||||
### Hierarchical Process
|
||||
- Uses a manager agent to coordinate task execution
|
||||
- Manager decides task order and agent assignments
|
||||
- Provides more complex task orchestration
|
||||
- Requires manager_llm parameter
|
||||
- Supports dynamic agent assignment
|
||||
|
||||
### Workflow Process
|
||||
- Supports complex task relationships
|
||||
- Features:
|
||||
- Task dependencies
|
||||
- Conditional execution
|
||||
- Loops
|
||||
- Context sharing between tasks
|
||||
- Maintains task state and relationships
|
||||
- Handles data flow between tasks
|
||||
@@ -0,0 +1,78 @@
|
||||
---
|
||||
title: "Task Module"
|
||||
description: "Documentation for the praisonaiagents.task.task module"
|
||||
icon: "list-check"
|
||||
---
|
||||
|
||||
# Module praisonaiagents.task.task
|
||||
|
||||
## Classes
|
||||
|
||||
### Task
|
||||
Represents a task to be executed by an agent.
|
||||
|
||||
#### Parameters
|
||||
- `description: str` - Task description
|
||||
- `expected_output: str` - Expected output description
|
||||
- `agent: Agent | None = None` - Agent assigned to the task
|
||||
- `name: str | None = None` - Task name
|
||||
- `tools: List[Any] | None = None` - Tools available for the task
|
||||
- `context: List[Task] | None = None` - Context from other tasks
|
||||
- `async_execution: bool | None = False` - Enable async execution
|
||||
- `config: Dict[str, Any] | None = None` - Task configuration
|
||||
- `output_file: str | None = None` - Output file path
|
||||
- `output_json: Type[BaseModel] | None = None` - JSON output schema
|
||||
- `output_pydantic: Type[BaseModel] | None = None` - Pydantic output schema
|
||||
- `callback: Any | None = None` - Task callback
|
||||
- `status: str = 'not started'` - Task status
|
||||
- `result: TaskOutput | None = None` - Task result
|
||||
- `create_directory: bool | None = False` - Create output directory
|
||||
- `id: int | None = None` - Task ID
|
||||
- `images: List[str] | None = None` - Task images
|
||||
- `next_tasks: List[str] | None = None` - Next tasks
|
||||
- `task_type: str = 'task'` - Task type
|
||||
- `condition: Dict[str, List[str]] | None = None` - Task conditions
|
||||
- `is_start: bool = False` - Is start task
|
||||
- `loop_state: Dict[str, str | int] | None = None` - Loop state
|
||||
|
||||
#### Async Support
|
||||
The Task class supports asynchronous execution through the following features:
|
||||
|
||||
- `async_execution`: Boolean flag to enable async execution
|
||||
- `callback`: Supports both sync and async callback functions
|
||||
- `execute_callback`: Internal async method for handling callbacks
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
from typing import Coroutine
|
||||
from praisonaiagents import Task, TaskOutput
|
||||
|
||||
# Define an async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await some_async_operation()
|
||||
print(f"Processed: {output.raw}")
|
||||
|
||||
# Create task with async execution
|
||||
task = Task(
|
||||
description="Async task example",
|
||||
expected_output="Async result",
|
||||
async_execution=True, # Enable async execution
|
||||
callback=async_callback # Async callback
|
||||
)
|
||||
```
|
||||
|
||||
#### Callback Types
|
||||
The Task class supports both synchronous and asynchronous callbacks:
|
||||
```python
|
||||
# Type definition
|
||||
callback: Optional[Union[
|
||||
Callable[[TaskOutput], Any], # Sync callback
|
||||
Callable[[TaskOutput], Coroutine[Any, Any, Any]] # Async callback
|
||||
]]
|
||||
```
|
||||
|
||||
#### Async Task States
|
||||
- `not started`: Initial state
|
||||
- `in progress`: Task is being executed
|
||||
- `completed`: Task finished successfully
|
||||
- `failed`: Task execution failed
|
||||
@@ -1,12 +1,19 @@
|
||||
# Auto Generation Mode
|
||||
---
|
||||
title: "Auto Generation Mode"
|
||||
description: "Guide to PraisonAI's automatic agent generation feature, supporting both CrewAI and AutoGen frameworks for automated task execution"
|
||||
icon: "robot"
|
||||
---
|
||||
|
||||
PraisonAI supports automatic agent generation with both CrewAI and AutoGen frameworks.
|
||||
PraisonAI supports automatic agent generation with PraisonAI Agents, CrewAI and AutoGen frameworks.
|
||||
|
||||
## Installation
|
||||
|
||||
Choose your preferred framework:
|
||||
|
||||
```bash
|
||||
# For PraisonAI Agents
|
||||
pip install praisonai
|
||||
|
||||
# For CrewAI
|
||||
pip install "praisonai[crewai]"
|
||||
|
||||
@@ -19,11 +26,16 @@ pip install "praisonai[crewai,autogen]"
|
||||
|
||||
## Usage
|
||||
|
||||
### With CrewAI (Default)
|
||||
### With PraisonAI Agents
|
||||
```bash
|
||||
praisonai --auto "create a movie script about Dog in Moon"
|
||||
```
|
||||
|
||||
### With CrewAI
|
||||
```bash
|
||||
praisonai --framework crewai --auto "create a movie script about Dog in Moon"
|
||||
```
|
||||
|
||||
### With AutoGen
|
||||
```bash
|
||||
praisonai --framework autogen --auto "create a movie script about Dog in Moon"
|
||||
@@ -1,4 +1,8 @@
|
||||
# PraisonAI Call
|
||||
---
|
||||
title: "PraisonAI Call"
|
||||
description: "Guide to PraisonAI's voice-based interaction feature enabling AI customer service through phone calls, including setup and tool integration"
|
||||
icon: "phone"
|
||||
---
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/m1cwrUG2iAk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Installation
|
||||
description: Set up PraisonAI in your development environment
|
||||
icon: download
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Requirements**
|
||||
|
||||
- Python 3.10 or higher
|
||||
- pip package manager
|
||||
- Virtual environment (recommended)
|
||||
</Note>
|
||||
|
||||
# Installing PraisonAI
|
||||
|
||||
Follow these steps to set up PraisonAI in your development environment.
|
||||
|
||||
<Steps>
|
||||
<Step title="Create Virtual Environment (Optional)">
|
||||
First, create and activate a virtual environment:
|
||||
<CodeGroup>
|
||||
```bash Mac/Linux
|
||||
python -m venv praisonai-env
|
||||
source praisonai-env/bin/activate
|
||||
```
|
||||
|
||||
```bash Windows
|
||||
python -m venv praisonai-env
|
||||
.\praisonai-env\Scripts\activate
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Install PraisonAI">
|
||||
Install the core package and tools:
|
||||
```bash Terminal
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Configure Environment">
|
||||
```bash Terminal
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys)
|
||||
You can also use other LLM providers like Anthropic, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Quick Start Guide"
|
||||
icon="bolt"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Build your first AI agent
|
||||
</Card>
|
||||
<Card
|
||||
title="API Reference"
|
||||
icon="code"
|
||||
href="/api/praisonaiagents/index"
|
||||
>
|
||||
Explore the API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: "Introduction"
|
||||
description: "Welcome to PraisonAI - The Next Generation AI Agent Framework"
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
<Note>
|
||||
PraisonAI is a powerful framework for building and deploying AI agents that can understand, reason, and execute complex tasks autonomously.
|
||||
</Note>
|
||||
|
||||
# What is PraisonAI?
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Styling for main elements
|
||||
style Start fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Output fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Process fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[" "]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
|
||||
style Task1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon1 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
subgraph Agent2[" "]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
|
||||
style Task2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon2 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
%% Style for agent containers
|
||||
style Agent1 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
style Agent2 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Global styles
|
||||
classDef default fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
linkStyle default stroke:#7C90A0,stroke-width:2px
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agents" icon="user-robot">
|
||||
Autonomous AI entities that can understand context and execute tasks
|
||||
</Card>
|
||||
<Card title="Tasks" icon="list-check">
|
||||
Units of work that agents can execute independently or collaboratively
|
||||
</Card>
|
||||
<Card title="Process" icon="diagram-project">
|
||||
Workflow management for coordinating agent activities
|
||||
</Card>
|
||||
<Card title="Tools" icon="toolbox">
|
||||
Extensible capabilities that agents can leverage
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Key Features
|
||||
|
||||
<Steps>
|
||||
<Step title="Autonomous Agents">
|
||||
Create intelligent agents that can:
|
||||
- Understand natural language instructions
|
||||
- Make decisions based on context
|
||||
- Execute complex tasks autonomously
|
||||
</Step>
|
||||
<Step title="Flexible Architecture">
|
||||
Build with:
|
||||
- Modular components
|
||||
- Extensible tools
|
||||
- Customizable workflows
|
||||
</Step>
|
||||
<Step title="Advanced Capabilities">
|
||||
Leverage:
|
||||
- Multi-agent collaboration
|
||||
- Memory and context management
|
||||
- Tool integration
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Use Cases
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Customer Service" icon="headset">
|
||||
Build intelligent support agents that can handle customer inquiries and resolve issues autonomously.
|
||||
</Card>
|
||||
<Card title="Data Analysis" icon="chart-line">
|
||||
Create agents that can process, analyze, and derive insights from complex datasets.
|
||||
</Card>
|
||||
<Card title="Content Creation" icon="pen-nib">
|
||||
Deploy agents that can generate, edit, and optimize content across various formats.
|
||||
</Card>
|
||||
<Card title="Process Automation" icon="gears">
|
||||
Automate complex workflows with intelligent agents that can coordinate and execute tasks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Getting Started
|
||||
|
||||
<Warning>
|
||||
Before proceeding, ensure you have Python 3.9+ installed on your system.
|
||||
</Warning>
|
||||
|
||||
### Quick Setup
|
||||
|
||||
<CodeGroup>
|
||||
```bash pip
|
||||
pip install praisonai
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Basic Example
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Installation"
|
||||
icon="download"
|
||||
href="/code/installation"
|
||||
>
|
||||
Complete installation guide and setup instructions
|
||||
</Card>
|
||||
<Card
|
||||
title="Quick Start"
|
||||
icon="play"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Build your first AI agent in minutes
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Join our community on [Discord](https://www.youtube.com/redirect?event=channel_description&redir_token=QUFFLUhqbUpiZE00YlF1MjB1LVNIeTFxTnV6MWRRc18wZ3xBQ3Jtc0ttQVZ0aFJ4RXRDanlBQU1Vd3lHU3BBcml3bzhoek1pTmlkZkFkWjlNVDBpRkxZd1dTOWhPc20xbHJOb1NibmNYeTEydklJT0pZOVJFQW93MmJOQXU0WkJNVzNsd29SZ3FBNFVwMTFGNThNSHBWVUhjSQ&q=https%3A%2F%2Fdiscord.gg%2FnNZu5gGT59) to connect with other developers and get help!
|
||||
</Tip>
|
||||
@@ -0,0 +1,195 @@
|
||||
---
|
||||
title: Quick Start
|
||||
description: Build your first AI agent with PraisonAI
|
||||
icon: bolt
|
||||
---
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Install PraisonAI">
|
||||
Install the core package:
|
||||
```bash Terminal
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Configure Environment">
|
||||
```bash Terminal
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys)
|
||||
You can also use other LLM providers like Anthropic, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create `app.py`:
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create multiple agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="You are a content strategist",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Define multiple tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="Create a blog post about AI advancements",
|
||||
expected_output="A blog post",
|
||||
agent=writer
|
||||
)
|
||||
|
||||
# Run with hierarchical process
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
verbose=False,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Program">
|
||||
Execute your script:
|
||||
```bash Terminal
|
||||
python app.py
|
||||
```
|
||||
|
||||
You should see:
|
||||
- Agent initialization
|
||||
- Agents progress
|
||||
- Final results
|
||||
- Generated report
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Creating Custom Tool
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from duckduckgo_search import DDGS
|
||||
from typing import List, Dict
|
||||
|
||||
# 1. Tool
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform Internet Search
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
# 2. Agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 3. Tasks
|
||||
collect_task = Task(
|
||||
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
|
||||
expected_output="List of search results with titles, URLs, and snippets.",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
)
|
||||
|
||||
# 4. Start Agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[collect_task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Core Concepts"
|
||||
icon="book"
|
||||
href="/concepts/agents"
|
||||
>
|
||||
Learn about agents, tasks, and processes
|
||||
</Card>
|
||||
<Card
|
||||
title="API Reference"
|
||||
icon="code"
|
||||
href="/api/praisonaiagents/index"
|
||||
>
|
||||
Explore detailed API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,235 @@
|
||||
---
|
||||
title: "Agents"
|
||||
description: "Understanding Agents in PraisonAI"
|
||||
icon: "user"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Agents are the core building blocks of PraisonAI. Each agent is an autonomous AI entity with specific roles, goals, and capabilities.
|
||||
</Note>
|
||||
|
||||
# Understanding Agents
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Styling for main elements
|
||||
style Start fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Output fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Process fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[" "]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
|
||||
style Task1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon1 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
subgraph Agent2[" "]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
|
||||
style Task2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon2 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
%% Style for agent containers
|
||||
style Agent1 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
style Agent2 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Global styles
|
||||
classDef default fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
linkStyle default stroke:#7C90A0,stroke-width:2px
|
||||
```
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Role & Goal" icon="target">
|
||||
Defines the agent's purpose and objectives through role definition and specific goals
|
||||
</Card>
|
||||
<Card title="Capabilities" icon="toolbox">
|
||||
Tools and functions available to the agent for task execution
|
||||
</Card>
|
||||
<Card title="Memory" icon="brain">
|
||||
Context retention and learning capabilities across interactions
|
||||
</Card>
|
||||
<Card title="Language Model" icon="microchip">
|
||||
The underlying AI model powering the agent's intelligence
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Component Details
|
||||
|
||||
### Role and Goal
|
||||
<Tip>
|
||||
Clear role and goal definitions are crucial for optimal agent performance.
|
||||
</Tip>
|
||||
|
||||
| Component | Description | Example |
|
||||
|:----------|:------------|:--------|
|
||||
| **Role** | Agent's function and expertise | Research Analyst, Code Developer |
|
||||
| **Goal** | Specific objectives to achieve | Analyze market trends, Generate reports |
|
||||
| **Backstory** | Contextual background | Expert with 10 years of experience |
|
||||
|
||||
### Capabilities
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
agent = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Agent Types
|
||||
|
||||
<Steps>
|
||||
<Step title="Basic Agent">
|
||||
- Single-purpose focus
|
||||
- Direct user interaction
|
||||
- Limited tool set
|
||||
</Step>
|
||||
<Step title="Specialized Agent">
|
||||
- Domain expertise
|
||||
- Advanced capabilities
|
||||
- Custom tools
|
||||
</Step>
|
||||
<Step title="Collaborative Agent">
|
||||
- Team interaction
|
||||
- Task delegation
|
||||
- Shared context
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<Warning>
|
||||
Always implement proper error handling and resource management in your agent configurations.
|
||||
</Warning>
|
||||
|
||||
### Agent Design
|
||||
1. Clear role definition
|
||||
2. Specific, measurable goals
|
||||
3. Relevant tool selection
|
||||
4. Appropriate memory configuration
|
||||
|
||||
### Agent Interaction
|
||||
1. Clear communication protocols
|
||||
2. Defined delegation rules
|
||||
3. Error handling mechanisms
|
||||
4. Resource management
|
||||
|
||||
## Advanced Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Memory Management" icon="brain">
|
||||
- Short-term conversation memory
|
||||
- Long-term knowledge retention
|
||||
- Context preservation
|
||||
</Card>
|
||||
<Card title="Tool Integration" icon="plug">
|
||||
- Custom tool development
|
||||
- External API integration
|
||||
- Resource access control
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Async Support
|
||||
Agents now support asynchronous operations through the following methods:
|
||||
|
||||
- `achat`: Async version of the chat method
|
||||
- `astart`: Async version of start method
|
||||
- `aexecute_task`: Async version of execute_task method
|
||||
- `arun_task`: Async version of run_task method
|
||||
- `arun_all_tasks`: Async version of run_all_tasks method
|
||||
|
||||
### Example Usage:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
async def main():
|
||||
# Create an async agent
|
||||
async_agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Async Task Specialist",
|
||||
goal="Perform async operations",
|
||||
backstory="Expert in async operations",
|
||||
tools=[async_search_tool], # Your async tool
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create an async task
|
||||
async_task = Task(
|
||||
description="Perform async operation",
|
||||
expected_output="Async result",
|
||||
agent=async_agent,
|
||||
async_execution=True # Enable async execution
|
||||
)
|
||||
|
||||
# Create and start agents with async support
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Start async execution
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the async main function
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Key Features:
|
||||
- Full async/await support
|
||||
- Parallel task execution
|
||||
- Async tool integration
|
||||
- Async callback support
|
||||
- Mixed sync/async operations
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Create Your First Agent"
|
||||
icon="code"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Follow our quickstart guide to create your first agent
|
||||
</Card>
|
||||
<Card
|
||||
title="API Reference"
|
||||
icon="book"
|
||||
href="/api/praisonaiagents/agent/agent"
|
||||
>
|
||||
Explore the complete Agent API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,220 @@
|
||||
---
|
||||
title: "Process"
|
||||
description: "Understanding Process Types in PraisonAI"
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
# Understanding Process Types
|
||||
|
||||
Process types in PraisonAI define how tasks are executed and how agents collaborate. Each process type offers different patterns for task execution and agent coordination.
|
||||
|
||||
## Process Types Overview
|
||||
|
||||
Three types of processes are implemented in PraisonAI:
|
||||
|
||||
<Frame>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16m-7 6h7" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Sequential Process</h3>
|
||||
</div>
|
||||
<p>Linear task execution in a predefined order</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Hierarchical Process</h3>
|
||||
</div>
|
||||
<p>Manager-coordinated task execution with dynamic assignment</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-purple-600 dark:text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Workflow Process</h3>
|
||||
</div>
|
||||
<p>Complex task flows with conditional execution and state management</p>
|
||||
</div>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Sequential Process
|
||||
The simplest form of task execution where tasks are performed one after another.
|
||||
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
#### Characteristics
|
||||
- Linear execution flow
|
||||
- Predictable order
|
||||
- Simple dependency management
|
||||
- Direct task progression
|
||||
|
||||
#### Usage
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent1, agent2],
|
||||
tasks=[task1, task2, task3],
|
||||
process="sequential"
|
||||
)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Hierarchical Process
|
||||
Uses a manager agent to coordinate task execution and agent assignments.
|
||||
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
#### Characteristics
|
||||
- Manager-driven coordination
|
||||
- Dynamic task assignment
|
||||
- Flexible execution order
|
||||
- Intelligent resource allocation
|
||||
|
||||
#### Configuration
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[manager_agent, worker_agent1, worker_agent2],
|
||||
tasks=[task1, task2],
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Workflow Process
|
||||
Advanced process type supporting complex task relationships and conditional execution.
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/yWTH44QPl2A"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
#### Features
|
||||
- Task dependencies
|
||||
- Conditional branching
|
||||
- Loop handling
|
||||
- Context sharing
|
||||
- State management
|
||||
|
||||
#### Implementation
|
||||
```python
|
||||
task_workflow = {
|
||||
"start_task": {
|
||||
"next": ["decision_task"],
|
||||
"type": "task"
|
||||
},
|
||||
"decision_task": {
|
||||
"type": "decision",
|
||||
"conditions": {
|
||||
"success": ["process_task"],
|
||||
"failure": ["error_task"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### State Management
|
||||
- Task state tracking
|
||||
- Context preservation
|
||||
- Data flow control
|
||||
|
||||
### Error Handling
|
||||
- Graceful failure recovery
|
||||
- Alternative path execution
|
||||
- Error reporting
|
||||
|
||||
### Monitoring
|
||||
- Progress tracking
|
||||
- Performance metrics
|
||||
- Resource utilization
|
||||
|
||||
### Integration
|
||||
- External system coordination
|
||||
- API synchronization
|
||||
- Event handling
|
||||
|
||||
## Async Process Execution
|
||||
All process types (sequential, workflow, hierarchical) support async execution through async generators. This enables efficient handling of async tasks and parallel processing.
|
||||
|
||||
### Async Process Methods
|
||||
- `asequential`: Async version of sequential process
|
||||
- `aworkflow`: Async version of workflow process
|
||||
- `ahierarchical`: Async version of hierarchical process
|
||||
|
||||
### Example Usage:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
async def main():
|
||||
# Create agents and tasks
|
||||
agents = [async_agent1, async_agent2]
|
||||
tasks = [async_task1, async_task2]
|
||||
|
||||
# Initialize PraisonAIAgents with async workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=agents,
|
||||
tasks=tasks,
|
||||
process="workflow" # or "sequential" or "hierarchical"
|
||||
)
|
||||
|
||||
# Start async execution
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the async workflow
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Async Process Features:
|
||||
- Parallel task execution in workflow
|
||||
- Async task delegation in hierarchical process
|
||||
- Non-blocking task execution
|
||||
- Efficient resource utilization
|
||||
- Mixed sync/async task support
|
||||
|
||||
### Process-Specific Async Behavior:
|
||||
1. **Sequential Process**:
|
||||
- Tasks are executed in order
|
||||
- Async tasks don't block other tasks
|
||||
- Maintains sequential order while allowing async execution
|
||||
|
||||
2. **Workflow Process**:
|
||||
- Parallel execution of independent tasks
|
||||
- Async branching and merging
|
||||
- Dynamic task scheduling
|
||||
|
||||
3. **Hierarchical Process**:
|
||||
- Async manager delegation
|
||||
- Parallel subtask execution
|
||||
- Dynamic task assignment
|
||||
@@ -0,0 +1,317 @@
|
||||
---
|
||||
title: "Tasks"
|
||||
description: "Understanding Tasks in PraisonAI"
|
||||
icon: "list-check"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Tasks are the fundamental units of work in PraisonAI, defining what needs to be done, how it should be done, and who should do it.
|
||||
</Note>
|
||||
|
||||
# Understanding Tasks
|
||||
|
||||
<Frame>
|
||||
<div className="p-6 bg-white dark:bg-gray-800 rounded-lg">
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
{/* Task Flow Steps */}
|
||||
<div className="flex justify-between items-center">
|
||||
{/* Task Definition */}
|
||||
<div className="flex-1 p-4 border-2 border-blue-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Task Definition</h4>
|
||||
<p className="text-sm mt-1">Description & Requirements</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow 1 */}
|
||||
<div className="flex-none px-4">
|
||||
<svg className="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Agent Assignment */}
|
||||
<div className="flex-1 p-4 border-2 border-green-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Agent Assignment</h4>
|
||||
<p className="text-sm mt-1">Matching & Delegation</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow 2 */}
|
||||
<div className="flex-none px-4">
|
||||
<svg className="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Execution */}
|
||||
<div className="flex-1 p-4 border-2 border-purple-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-purple-600 dark:text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Execution</h4>
|
||||
<p className="text-sm mt-1">Processing & Tools</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow 3 */}
|
||||
<div className="flex-none px-4">
|
||||
<svg className="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Output */}
|
||||
<div className="flex-1 p-4 border-2 border-yellow-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-yellow-100 dark:bg-yellow-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-yellow-600 dark:text-yellow-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Output</h4>
|
||||
<p className="text-sm mt-1">Results & Validation</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Task States */}
|
||||
<div className="grid grid-cols-4 gap-4 mt-4">
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-blue-50 dark:bg-blue-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">Pending</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-yellow-50 dark:bg-yellow-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">In Progress</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-green-50 dark:bg-green-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">Completed</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-red-50 dark:bg-red-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">Failed</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Core Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Task Definition" icon="file-lines">
|
||||
Clear description of work to be done and expected outputs
|
||||
</Card>
|
||||
<Card title="Agent Assignment" icon="user-check">
|
||||
Matching tasks with capable agents
|
||||
</Card>
|
||||
<Card title="Tool Access" icon="toolbox">
|
||||
Resources available for task completion
|
||||
</Card>
|
||||
<Card title="Output Handling" icon="file-export">
|
||||
Managing and formatting task results
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Task Configuration
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
task = Task(
|
||||
description="Research AI trends",
|
||||
expected_output="Summary report",
|
||||
agent=research_agent
|
||||
)
|
||||
```
|
||||
```python Advanced
|
||||
task = Task(
|
||||
description="Analyze market data",
|
||||
expected_output="Detailed analysis",
|
||||
agent=analyst_agent,
|
||||
tools=[AnalysisTool()],
|
||||
output_file="analysis.md",
|
||||
async_execution=True
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Task Types
|
||||
|
||||
<Steps>
|
||||
<Step title="Basic Task">
|
||||
Simple, single-operation tasks with clear inputs and outputs
|
||||
</Step>
|
||||
<Step title="Decision Task">
|
||||
Tasks involving choices and conditional paths
|
||||
```python
|
||||
decision_task = Task(
|
||||
type="decision",
|
||||
conditions={
|
||||
"success": ["next_task"],
|
||||
"failure": ["error_task"]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
<Step title="Loop Task">
|
||||
Repetitive operations over collections
|
||||
```python
|
||||
loop_task = Task(
|
||||
type="loop",
|
||||
items=data_list,
|
||||
operation="process_item"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Task Relationships
|
||||
|
||||
<Warning>
|
||||
Properly managing task dependencies is crucial for complex workflows. Always ensure proper context sharing and error handling.
|
||||
</Warning>
|
||||
|
||||
### Context Sharing
|
||||
```python
|
||||
task_a = Task(name="research")
|
||||
task_b = Task(
|
||||
name="analyze",
|
||||
context=[task_a] # Uses task_a's output
|
||||
)
|
||||
```
|
||||
|
||||
### Task Dependencies
|
||||
|
||||
| Relationship | Description | Example |
|
||||
|:-------------|:------------|:--------|
|
||||
| **Sequential** | Tasks run one after another | Research → Analysis → Report |
|
||||
| **Parallel** | Independent tasks run simultaneously | Data Collection + Processing |
|
||||
| **Conditional** | Tasks depend on previous results | Success → Next Task, Failure → Retry |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Output Handling" icon="file-code">
|
||||
- Multiple output formats
|
||||
- Structured data validation
|
||||
- File system integration
|
||||
</Card>
|
||||
<Card title="Task Control" icon="sliders">
|
||||
- Execution flow control
|
||||
- Error recovery
|
||||
- Progress tracking
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<Tip>
|
||||
Design tasks to be atomic and focused. Each task should have a single, clear responsibility.
|
||||
</Tip>
|
||||
|
||||
1. Clear task descriptions
|
||||
2. Well-defined success criteria
|
||||
3. Appropriate tool selection
|
||||
4. Error handling consideration
|
||||
5. Resource management
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Create Tasks"
|
||||
icon="plus"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Learn how to create and configure tasks
|
||||
</Card>
|
||||
<Card
|
||||
title="Task API"
|
||||
icon="code"
|
||||
href="/api/praisonaiagents/task/task"
|
||||
>
|
||||
Explore the complete Task API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Async Task Execution
|
||||
Tasks can be executed asynchronously by setting `async_execution=True`. This is particularly useful for tasks that involve I/O operations or when you want to run multiple tasks in parallel.
|
||||
|
||||
### Async Task Configuration
|
||||
```python
|
||||
async_task = Task(
|
||||
description="Perform async operation",
|
||||
expected_output="Async result",
|
||||
agent=async_agent,
|
||||
async_execution=True, # Enable async execution
|
||||
callback=async_callback # Optional async callback
|
||||
)
|
||||
```
|
||||
|
||||
### Async Callbacks
|
||||
Tasks support both synchronous and asynchronous callbacks:
|
||||
|
||||
```python
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate async operation
|
||||
print(f"Processed output: {output.raw}")
|
||||
|
||||
# Task with async callback
|
||||
task = Task(
|
||||
description="Task with async callback",
|
||||
expected_output="Result",
|
||||
agent=agent,
|
||||
async_execution=True,
|
||||
callback=async_callback
|
||||
)
|
||||
```
|
||||
|
||||
### Mixing Sync and Async Tasks
|
||||
You can mix synchronous and asynchronous tasks in the same workflow:
|
||||
|
||||
```python
|
||||
# Sync task
|
||||
sync_task = Task(
|
||||
description="Synchronous operation",
|
||||
expected_output="Sync result",
|
||||
agent=sync_agent,
|
||||
async_execution=False
|
||||
)
|
||||
|
||||
# Async task
|
||||
async_task = Task(
|
||||
description="Asynchronous operation",
|
||||
expected_output="Async result",
|
||||
agent=async_agent,
|
||||
async_execution=True
|
||||
)
|
||||
|
||||
# Create agents with mixed tasks
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent, async_agent],
|
||||
tasks=[sync_task, async_task]
|
||||
)
|
||||
|
||||
# Run asynchronously
|
||||
result = await agents.astart()
|
||||
```
|
||||
@@ -0,0 +1,335 @@
|
||||
---
|
||||
title: "Tools"
|
||||
description: "Understanding Tools in PraisonAI"
|
||||
icon: "screwdriver-wrench"
|
||||
---
|
||||
|
||||
# Understanding Tools
|
||||
|
||||
Tools in PraisonAI are functions that agents can use to interact with external systems, perform computations, or access data. They extend the capabilities of agents beyond just language processing.
|
||||
|
||||
## Tools Overview
|
||||
|
||||
<Frame>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Search Tools</h3>
|
||||
</div>
|
||||
<p>Tools for searching and retrieving information from various sources</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">File Tools</h3>
|
||||
</div>
|
||||
<p>Tools for reading, writing, and manipulating files</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-purple-600 dark:text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">API Tools</h3>
|
||||
</div>
|
||||
<p>Tools for interacting with external APIs and services</p>
|
||||
</div>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Creating Custom Tool
|
||||
<Steps>
|
||||
<Step>
|
||||
Create any function that you want to use as a tool, that performs a specific task.
|
||||
```python
|
||||
from duckduckgo_search import DDGS
|
||||
from typing import List, Dict
|
||||
|
||||
# Tool Implementation
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform Internet Search using DuckDuckGo
|
||||
|
||||
Args:
|
||||
query (str): The search query string
|
||||
|
||||
Returns:
|
||||
List[Dict]: List of search results containing title, URL, and snippet
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
```
|
||||
</Step>
|
||||
<Step>
|
||||
Assign the tool to an agent
|
||||
```python
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool], ## Add the tool to the agent i.e the function name
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Card title="That's it!">
|
||||
<Check>You have created a custom tool and assigned it to an agent.</Check>
|
||||
</Card>
|
||||
|
||||
## Implementing Tools Full Code Example
|
||||
|
||||
Tools are implemented as Python functions with type hints and docstrings. Here's a complete example:
|
||||
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from duckduckgo_search import DDGS
|
||||
from typing import List, Dict
|
||||
|
||||
# 1. Tool Implementation
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform Internet Search using DuckDuckGo
|
||||
|
||||
Args:
|
||||
query (str): The search query string
|
||||
|
||||
Returns:
|
||||
List[Dict]: List of search results containing title, URL, and snippet
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
# 2. Assign the tool to an agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 3. Task Definition
|
||||
collect_task = Task(
|
||||
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
|
||||
expected_output="List of search results with titles, URLs, and snippets.",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
)
|
||||
|
||||
# 4. Start Agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[collect_task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Advanced Tool Features
|
||||
|
||||
### Tool Configuration
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
def configured_tool(
|
||||
query: str,
|
||||
max_results: int = 5,
|
||||
timeout: int = 10
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
Example of a configurable tool
|
||||
|
||||
Args:
|
||||
query (str): Search query
|
||||
max_results (int): Maximum number of results
|
||||
timeout (int): Request timeout in seconds
|
||||
|
||||
Returns:
|
||||
List[Dict]: Search results
|
||||
"""
|
||||
# Tool implementation
|
||||
pass
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Tool Chaining
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
def chain_tools(input_data: str) -> Dict:
|
||||
"""
|
||||
Example of chaining multiple tools
|
||||
|
||||
Args:
|
||||
input_data (str): Input data
|
||||
|
||||
Returns:
|
||||
Dict: Processed results
|
||||
"""
|
||||
# 1. Search for data
|
||||
search_results = internet_search_tool(input_data)
|
||||
|
||||
# 2. Process results
|
||||
processed_data = process_tool(search_results)
|
||||
|
||||
# 3. Format output
|
||||
return format_tool(processed_data)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Tool Categories
|
||||
|
||||
1. **Data Collection Tools**
|
||||
- Web scraping
|
||||
- API integration
|
||||
- Database queries
|
||||
|
||||
2. **Processing Tools**
|
||||
- Data transformation
|
||||
- Text analysis
|
||||
- Image processing
|
||||
|
||||
3. **Output Tools**
|
||||
- File generation
|
||||
- Report creation
|
||||
- Data visualization
|
||||
|
||||
## Tool Integration
|
||||
|
||||
### Adding Tools to Agents
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
# Multiple tools
|
||||
agent = Agent(
|
||||
name="MultiTool Agent",
|
||||
tools=[
|
||||
internet_search_tool,
|
||||
file_processing_tool,
|
||||
api_integration_tool
|
||||
]
|
||||
)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Tool Dependencies
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
# Tool with dependencies
|
||||
def advanced_tool(data: Dict) -> Dict:
|
||||
"""
|
||||
Tool that depends on external libraries
|
||||
|
||||
Args:
|
||||
data (Dict): Input data
|
||||
|
||||
Returns:
|
||||
Dict: Processed data
|
||||
"""
|
||||
try:
|
||||
import required_library
|
||||
# Tool implementation
|
||||
return processed_result
|
||||
except ImportError:
|
||||
raise Exception("Required library not installed")
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Tool Guidelines
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-lg font-semibold mb-3">Best Practices</h3>
|
||||
1. **Type Hints**
|
||||
- Use Python type hints
|
||||
- Define clear input/output types
|
||||
- Document complex types
|
||||
|
||||
2. **Documentation**
|
||||
- Write clear docstrings
|
||||
- Explain parameters
|
||||
- Provide usage examples
|
||||
|
||||
3. **Error Handling**
|
||||
- Handle exceptions gracefully
|
||||
- Return meaningful errors
|
||||
- Validate inputs
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-lg font-semibold mb-3">Tool Types</h3>
|
||||
1. **Search Tools**
|
||||
- Web search
|
||||
- Database queries
|
||||
- Document search
|
||||
|
||||
2. **File Tools**
|
||||
- Read/write operations
|
||||
- File conversion
|
||||
- Data extraction
|
||||
|
||||
3. **API Tools**
|
||||
- REST API calls
|
||||
- GraphQL queries
|
||||
- Service integration
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Best Practices Summary
|
||||
|
||||
1. **Design Principles**
|
||||
- Single responsibility
|
||||
- Clear interfaces
|
||||
- Proper documentation
|
||||
- Error handling
|
||||
|
||||
2. **Performance**
|
||||
- Efficient processing
|
||||
- Resource management
|
||||
- Caching when appropriate
|
||||
- Asynchronous operations
|
||||
|
||||
3. **Security**
|
||||
- Input validation
|
||||
- Rate limiting
|
||||
- API key management
|
||||
- Error masking
|
||||
@@ -1,4 +1,8 @@
|
||||
# Contributing
|
||||
---
|
||||
title: "Contributing"
|
||||
description: "Guide for contributing to PraisonAI through GitHub, including forking, cloning, and submitting pull requests"
|
||||
icon: "code-branch"
|
||||
---
|
||||
|
||||
- Fork on GitHub: Use the "Fork" button on the repository page.
|
||||
- Clone your fork: `git clone https://github.com/yourusername/praisonAI.git`
|
||||
@@ -1,4 +1,8 @@
|
||||
# Deploy
|
||||
---
|
||||
title: "Deploy"
|
||||
description: "Guide for deploying PraisonAI to cloud platforms, with detailed instructions for Google Cloud deployment"
|
||||
icon: "cloud"
|
||||
---
|
||||
|
||||
## Google Cloud
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
title: "Agents Playbook"
|
||||
description: "Examples and templates for creating PraisonAI agent playbooks, from simple to detailed configurations with multiple roles and tasks"
|
||||
icon: "book"
|
||||
---
|
||||
|
||||
# Agents Playbook
|
||||
|
||||
## Simple Playbook Example
|
||||
@@ -1,4 +1,10 @@
|
||||
---
|
||||
title: "Google Colab Tools"
|
||||
description: "Guide for implementing and using custom tools in PraisonAI with Google Colab, including examples of internet search and data processing tools"
|
||||
icon: "wrench"
|
||||
---
|
||||
|
||||
```
|
||||
jupyter:
|
||||
accelerator: GPU
|
||||
colab:
|
||||
@@ -10,7 +16,7 @@ jupyter:
|
||||
name: python
|
||||
nbformat: 4
|
||||
nbformat_minor: 0
|
||||
---
|
||||
```
|
||||
|
||||
``` python
|
||||
!pip install -Uq praisonai duckduckgo_search
|
||||
@@ -1,4 +1,23 @@
|
||||
---
|
||||
title: "Google Colab Integration"
|
||||
description: "Guide for using PraisonAI in Google Colab environments, with example code and configurations for agent-based tasks"
|
||||
icon: "google"
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Basic PraisonAI" icon="book">
|
||||
<a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-googlecolab.ipynb">
|
||||
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" />
|
||||
</a>
|
||||
</Card>
|
||||
<Card title="PraisonAI with Tools" icon="screwdriver-wrench">
|
||||
<a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb">
|
||||
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" />
|
||||
</a>
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
```
|
||||
jupyter:
|
||||
accelerator: GPU
|
||||
colab:
|
||||
@@ -10,7 +29,7 @@ jupyter:
|
||||
name: python
|
||||
nbformat: 4
|
||||
nbformat_minor: 0
|
||||
---
|
||||
```
|
||||
|
||||
|
||||
``` python
|
||||
@@ -1,5 +0,0 @@
|
||||
# Test
|
||||
|
||||
```bash
|
||||
python -m unittest tests.test
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "Test"
|
||||
description: "Instructions for running and writing tests for PraisonAI components, including unit tests and test automation"
|
||||
icon: "vial"
|
||||
---
|
||||
|
||||
# Test
|
||||
|
||||
```bash
|
||||
python -m unittest tests.test
|
||||
```
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
title: "Integrate with Tools"
|
||||
description: "Guide for integrating external tools and APIs with PraisonAI, including examples of custom tool creation and implementation"
|
||||
icon: "plug"
|
||||
---
|
||||
|
||||
# Integrate with Tools
|
||||
|
||||
```python
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
title: "PraisonAI Package Integration"
|
||||
description: "Guide for integrating the PraisonAI package into your Python projects, including YAML configuration and different execution modes"
|
||||
icon: "box"
|
||||
---
|
||||
|
||||
# Include praisonai package in your project
|
||||
|
||||
## Option 1: Using RAW YAML
|
||||
@@ -0,0 +1,494 @@
|
||||
---
|
||||
title: "Async AI Agents"
|
||||
description: "Async AI Agents allow you to run AI tasks asynchronously, improving performance and efficiency in your applications."
|
||||
icon: "clock"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Requirements**
|
||||
|
||||
- Python 3.10 or higher
|
||||
- Basic understanding of async/await in Python
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your OpenAI API key as an environment variable:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key_here
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Project">
|
||||
Create a new file `app.py` with the basic setup:
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Assistant",
|
||||
goal="Help with tasks",
|
||||
backstory="Expert in async operations"
|
||||
)
|
||||
|
||||
# Create a task
|
||||
task = Task(
|
||||
name="hello_task",
|
||||
description="Say hello and introduce yourself",
|
||||
agent=agent,
|
||||
async_execution=True,
|
||||
expected_output="Answer to the question"
|
||||
)
|
||||
|
||||
# Create agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Main async function
|
||||
async def main():
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the program
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Program">
|
||||
Run your async AI agent:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/VhVQfgo00LE"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Understanding Async Execution
|
||||
|
||||
<Card title="What is Asynchronous Execution?" icon="question">
|
||||
Async execution lets your program continue running while waiting for operations to complete. This is ideal for:
|
||||
- Making multiple AI API calls
|
||||
- Processing large datasets
|
||||
- Handling multiple tasks simultaneously
|
||||
- Maintaining responsive applications
|
||||
</Card>
|
||||
|
||||
<CodeGroup>
|
||||
```python Sync
|
||||
# Synchronous execution (blocks until complete)
|
||||
result = agent.chat("Hello")
|
||||
```
|
||||
|
||||
```python Async
|
||||
# Asynchronous execution (non-blocking)
|
||||
result = await agent.achat("Hello")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Async Tasks" icon="tasks">
|
||||
Create tasks that run asynchronously with built-in error handling and retries.
|
||||
</Card>
|
||||
<Card title="Parallel Processing" icon="arrows-split-up-and-left">
|
||||
Run multiple tasks in parallel using asyncio.gather().
|
||||
</Card>
|
||||
<Card title="Mixed Mode" icon="shuffle">
|
||||
Mix sync and async tasks in the same workflow seamlessly.
|
||||
</Card>
|
||||
<Card title="Resource Management" icon="gear">
|
||||
Built-in resource management and performance optimization.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Async Tasks with Callbacks and Tools Example Code
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
# 1. Define async tool
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
async def async_search_tool(query: str) -> Dict:
|
||||
"""
|
||||
Asynchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
dict: Search results in SearchResult model format
|
||||
"""
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
|
||||
# Format response to match SearchResult model
|
||||
return {
|
||||
"query": query,
|
||||
"results": results,
|
||||
"total_results": len(results)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error during async search: {e}")
|
||||
return {
|
||||
"query": query,
|
||||
"results": [],
|
||||
"total_results": 0
|
||||
}
|
||||
|
||||
# 2. Define async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
print(f"Processed JSON result: {output.json_dict}")
|
||||
elif output.output_format == "Pydantic":
|
||||
print(f"Processed Pydantic result: {output.pydantic}")
|
||||
|
||||
# 3. Create specialized agents
|
||||
async_agent = Agent(
|
||||
name="AsyncSearchAgent",
|
||||
role="Asynchronous Search Specialist",
|
||||
goal="Perform fast and efficient asynchronous searches with structured results",
|
||||
backstory="Expert in parallel search operations and data retrieval",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
summary_agent = Agent(
|
||||
name="SummaryAgent",
|
||||
role="Research Synthesizer",
|
||||
goal="Create comprehensive summaries and identify patterns across multiple search results",
|
||||
backstory="""Expert in analyzing and synthesizing information from multiple sources.
|
||||
Skilled at identifying patterns, trends, and connections between different topics.
|
||||
Specializes in creating clear, structured summaries that highlight key insights.""",
|
||||
self_reflect=True, # Enable self-reflection for better summary quality
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 4. Create async tasks
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="""Search for 'Async programming' and return results in the following JSON format:
|
||||
{
|
||||
"query": "the search query",
|
||||
"results": [
|
||||
{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}
|
||||
],
|
||||
"total_results": number of results
|
||||
}""",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
# 5. Example usage functions
|
||||
async def run_single_task():
|
||||
"""Run single async task"""
|
||||
print("\nRunning Single Async Task...")
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
print(f"Single Task Result: {result}")
|
||||
|
||||
async def run_parallel_tasks():
|
||||
"""Run multiple async tasks in parallel"""
|
||||
print("\nRunning Parallel Async Tasks...")
|
||||
|
||||
# Define different search topics
|
||||
search_topics = [
|
||||
"Latest AI Developments 2024",
|
||||
"Machine Learning Best Practices",
|
||||
"Neural Networks Architecture"
|
||||
]
|
||||
|
||||
# Create tasks for different topics
|
||||
parallel_tasks = [
|
||||
Task(
|
||||
name=f"search_task_{i}",
|
||||
description=f"""Search for '{topic}' and return results in the following JSON format:
|
||||
{{
|
||||
"query": "{topic}",
|
||||
"results": [
|
||||
{{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}}
|
||||
],
|
||||
"total_results": number of results
|
||||
}}""",
|
||||
expected_output="SearchResult model with detailed information",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_pydantic=SearchResult
|
||||
) for i, topic in enumerate(search_topics)
|
||||
]
|
||||
|
||||
# Create summarization task with the specialized summary agent
|
||||
summary_task = Task(
|
||||
name="summary_task",
|
||||
description="""As a Research Synthesizer, analyze the search results and create a comprehensive summary. Your task:
|
||||
|
||||
1. Analyze Results:
|
||||
- Review all search results thoroughly
|
||||
- Extract key findings from each topic
|
||||
- Identify main themes and concepts
|
||||
|
||||
2. Find Connections:
|
||||
- Identify relationships between topics
|
||||
- Spot common patterns or contradictions
|
||||
- Note emerging trends across sources
|
||||
|
||||
3. Create Structured Summary:
|
||||
- Main findings per topic
|
||||
- Cross-cutting themes
|
||||
- Emerging trends
|
||||
- Practical implications
|
||||
- Future directions
|
||||
|
||||
4. Quality Checks:
|
||||
- Ensure all topics are covered
|
||||
- Verify accuracy of connections
|
||||
- Confirm clarity of insights
|
||||
- Validate practical relevance
|
||||
|
||||
Present the summary in a clear, structured format with sections for findings, patterns, trends, and implications.""",
|
||||
expected_output="""A comprehensive research synthesis containing:
|
||||
- Detailed findings from each search topic
|
||||
- Cross-topic patterns and relationships
|
||||
- Emerging trends and their implications
|
||||
- Practical applications and future directions""",
|
||||
agent=summary_agent, # Use the specialized summary agent
|
||||
async_execution=False, # Run synchronously after search tasks
|
||||
callback=async_callback
|
||||
)
|
||||
|
||||
# Create a single PraisonAIAgents instance with both agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent, summary_agent], # Include both agents
|
||||
tasks=parallel_tasks + [summary_task], # Include all tasks
|
||||
verbose=1,
|
||||
process="sequential" # Tasks will run in sequence, with parallel tasks running first
|
||||
)
|
||||
|
||||
# Run all tasks
|
||||
results = await agents.astart()
|
||||
print(f"Tasks Results: {results}")
|
||||
|
||||
# Return results in a serializable format
|
||||
return {
|
||||
"search_results": {
|
||||
"task_status": {k: v for k, v in results["task_status"].items() if k != summary_task.id},
|
||||
"task_results": [str(results["task_results"][i]) if results["task_results"][i] else None
|
||||
for i in range(len(parallel_tasks))]
|
||||
},
|
||||
"summary": str(results["task_results"][summary_task.id]) if results["task_results"].get(summary_task.id) else None,
|
||||
"topics": search_topics
|
||||
}
|
||||
|
||||
# 6. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
print("Starting Async AI Agents Examples...")
|
||||
|
||||
try:
|
||||
# Run different async patterns
|
||||
await run_single_task()
|
||||
await run_parallel_tasks()
|
||||
except Exception as e:
|
||||
print(f"Error in main execution: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
### 1. Async Tasks with Callbacks
|
||||
|
||||
<CodeGroup>
|
||||
```python Task
|
||||
# Create an async task with callback
|
||||
async_task = Task(
|
||||
name="weather_task",
|
||||
description="Check weather conditions",
|
||||
agent=agent,
|
||||
async_execution=True,
|
||||
callback=async_callback
|
||||
)
|
||||
```
|
||||
|
||||
```python Callback
|
||||
async def async_callback(output):
|
||||
await process_result(output)
|
||||
await save_to_database(output)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Parallel Task Processing
|
||||
|
||||
<Warning>
|
||||
Be mindful of rate limits and resource usage when processing tasks in parallel.
|
||||
</Warning>
|
||||
|
||||
```python
|
||||
async def process_multiple_tasks():
|
||||
tasks = [
|
||||
Task(
|
||||
name=f"task_{i}",
|
||||
description=f"Process item {i}",
|
||||
async_execution=True
|
||||
) for i in range(5)
|
||||
]
|
||||
|
||||
results = await asyncio.gather(
|
||||
*[agent.achat(task.description) for task in tasks]
|
||||
)
|
||||
return results
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error Handling">
|
||||
```python
|
||||
async def safe_async_operation():
|
||||
try:
|
||||
result = await agent.achat("Process this")
|
||||
return result
|
||||
except Exception as e:
|
||||
logging.error(f"Error: {e}")
|
||||
return None
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Resource Management">
|
||||
```python
|
||||
async def efficient_processing():
|
||||
semaphore = asyncio.Semaphore(5)
|
||||
async with semaphore:
|
||||
result = await agent.achat("Process within limits")
|
||||
return result
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Performance Tips">
|
||||
- Use `asyncio.gather()` for parallel operations
|
||||
- Implement proper error handling
|
||||
- Monitor memory usage
|
||||
- Use timeouts for long-running operations
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="ChatCompletion Error" icon="triangle-exclamation">
|
||||
If you see "ChatCompletion can't be used in await expression":
|
||||
- Use AsyncOpenAI() client
|
||||
- Ensure proper async context
|
||||
</Card>
|
||||
|
||||
<Card title="Event Loop Error" icon="circle-exclamation">
|
||||
If you get "Event loop is closed":
|
||||
- Use asyncio.run() for main entry
|
||||
- Check async context
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## API Reference
|
||||
|
||||
### Async Methods
|
||||
|
||||
<ResponseField name="achat()" type="async">
|
||||
Async version of chat method
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="aexecute_tool()" type="async">
|
||||
Async tool execution method
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="astart()" type="async">
|
||||
Async task execution starter
|
||||
</ResponseField>
|
||||
|
||||
### Task Properties
|
||||
|
||||
<ResponseField name="async_execution" type="boolean">
|
||||
Enable/disable async mode for tasks
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="callback" type="function">
|
||||
Set sync or async callback function
|
||||
</ResponseField>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Examples" icon="code" href="./examples">
|
||||
Check out more examples in our examples directory
|
||||
</Card>
|
||||
<Card title="Advanced Topics" icon="book" href="./advanced">
|
||||
Learn about advanced async patterns and optimizations
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Remember to handle errors properly, manage resources efficiently, and test thoroughly in async contexts.
|
||||
</Note>
|
||||
@@ -0,0 +1,782 @@
|
||||
---
|
||||
title: "Callbacks"
|
||||
description: "Learn how to implement callbacks to monitor and log AI agent interactions, errors, and task completions."
|
||||
icon: "bell"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.8 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of Python functions
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Required Functions">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import (
|
||||
register_display_callback,
|
||||
Agent,
|
||||
Task,
|
||||
PraisonAIAgents
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create a Simple Callback">
|
||||
Define your first callback function:
|
||||
```python
|
||||
def simple_callback(message=None, response=None, **kwargs):
|
||||
print(f"Received message: {message}")
|
||||
print(f"Got response: {response}")
|
||||
|
||||
# Register as synchronous callback
|
||||
register_display_callback('interaction', simple_callback, is_async=False)
|
||||
|
||||
# For async callbacks
|
||||
async def async_simple_callback(message=None, response=None, **kwargs):
|
||||
await asyncio.sleep(0) # Non-blocking pause
|
||||
print(f"Received message: {message}")
|
||||
print(f"Got response: {response}")
|
||||
|
||||
# Register as async callback
|
||||
register_display_callback('interaction', async_simple_callback, is_async=True)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Use in Your Code">
|
||||
Create and run an agent with callbacks enabled:
|
||||
```python
|
||||
# Create an agent
|
||||
agent = Agent(
|
||||
name="MyAgent",
|
||||
role="Assistant",
|
||||
goal="Help with tasks",
|
||||
backstory="I am a helpful assistant",
|
||||
verbose=True # Enable verbose mode to see callbacks in action
|
||||
)
|
||||
|
||||
# Create a task
|
||||
task = Task(
|
||||
name="simple_task",
|
||||
description="Say hello",
|
||||
agent=agent,
|
||||
expected_output="A greeting"
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task]
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
PraisonAI Agents supports both synchronous and asynchronous callbacks. When registering a callback, specify `is_async=True` for async callbacks. Both sync and async callbacks for the same display type can be executed simultaneously.
|
||||
</Note>
|
||||
|
||||
## Understanding Callbacks
|
||||
|
||||
<Card title="What are Callbacks?" icon="question">
|
||||
Callbacks are functions that get called automatically when specific events occur in your AI agents:
|
||||
- Interactions between user and agent
|
||||
- Error messages
|
||||
- Tool calls
|
||||
- Self-reflection moments
|
||||
- Task completion
|
||||
- Generation progress
|
||||
</Card>
|
||||
|
||||
## Available Callback Types
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Interaction Callback" icon="comments">
|
||||
Triggered when the agent interacts with users
|
||||
</Card>
|
||||
<Card title="Error Callback" icon="triangle-exclamation">
|
||||
Called when errors occur
|
||||
</Card>
|
||||
<Card title="Tool Call Callback" icon="wrench">
|
||||
Activated when tools are used
|
||||
</Card>
|
||||
<Card title="Self Reflection Callback" icon="brain">
|
||||
Triggered during agent self-reflection
|
||||
</Card>
|
||||
<Card title="Instruction Callback" icon="list-check">
|
||||
Called when instructions are processed
|
||||
</Card>
|
||||
<Card title="Generating Callback" icon="spinner">
|
||||
Activated during content generation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Basic Implementation
|
||||
|
||||
### 1. Simple Logging Callback
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
def log_callback(message=None, **kwargs):
|
||||
logging.info(f"Agent message: {message}")
|
||||
|
||||
# Register synchronous callback
|
||||
register_display_callback('interaction', log_callback, is_async=False)
|
||||
|
||||
# Register asynchronous callback
|
||||
async def async_log_callback(message=None, **kwargs):
|
||||
await asyncio.sleep(0)
|
||||
logging.info(f"Agent message: {message}")
|
||||
|
||||
# Register as async callback
|
||||
register_display_callback('interaction', async_log_callback, is_async=True)
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
# Setup logging with file output
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
def detailed_callback(message=None, response=None, **kwargs):
|
||||
logging.info(f"""
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Additional Info: {kwargs}
|
||||
""")
|
||||
|
||||
register_display_callback('interaction', detailed_callback)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Multiple Callback Types
|
||||
|
||||
```python
|
||||
# Error callback
|
||||
def error_callback(message=None):
|
||||
logging.error(f"Error occurred: {message}")
|
||||
|
||||
# Tool call callback
|
||||
def tool_callback(message=None):
|
||||
logging.info(f"Tool called: {message}")
|
||||
|
||||
# Register multiple callbacks
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_callback)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error Handling">
|
||||
Always include error handling in your callbacks:
|
||||
```python
|
||||
def safe_callback(message=None, **kwargs):
|
||||
try:
|
||||
# Process the callback
|
||||
logging.info(message)
|
||||
except Exception as e:
|
||||
logging.error(f"Callback error: {e}")
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Performance">
|
||||
Keep callbacks lightweight:
|
||||
```python
|
||||
# Good - Quick logging
|
||||
def good_callback(message=None):
|
||||
logging.info(message)
|
||||
|
||||
# Bad - Heavy processing
|
||||
def bad_callback(message=None):
|
||||
time.sleep(1) # Delays agent execution
|
||||
process_heavy_task(message)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Complete Example
|
||||
|
||||
Here's a full implementation showing all callback types and proper logging:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, register_display_callback
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Interaction callback
|
||||
def interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
logging.info(f"""
|
||||
=== INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Markdown: {markdown}
|
||||
""")
|
||||
|
||||
# Error callback
|
||||
def error_callback(message=None):
|
||||
logging.error(f"""
|
||||
=== ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
# Tool call callback
|
||||
def tool_call_callback(message=None):
|
||||
logging.info(f"""
|
||||
=== TOOL CALL ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
# Register callbacks
|
||||
register_display_callback('interaction', interaction_callback)
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
|
||||
agent = Agent(
|
||||
name="CallbackAgent",
|
||||
role="Assistant",
|
||||
goal="Demonstrate callbacks",
|
||||
backstory="I am a helpful assistant",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
task = Task(
|
||||
name="callback_task",
|
||||
description="Show how callbacks work",
|
||||
agent=agent,
|
||||
expected_output="Demonstration complete"
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Advanced Examples
|
||||
|
||||
- All callback types
|
||||
- Comprehensive logging
|
||||
- Task callbacks
|
||||
- Tool integration
|
||||
- Multiple agents
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs, register_display_callback
|
||||
from duckduckgo_search import DDGS
|
||||
from rich.console import Console
|
||||
import json
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Callback functions for different display types
|
||||
def interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
"""Callback for display_interaction"""
|
||||
logging.info(f"""
|
||||
=== INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Markdown: {markdown}
|
||||
""")
|
||||
|
||||
def error_callback(message=None):
|
||||
"""Callback for display_error"""
|
||||
logging.error(f"""
|
||||
=== ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def tool_call_callback(message=None):
|
||||
"""Callback for display_tool_call"""
|
||||
logging.info(f"""
|
||||
=== TOOL CALL ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def instruction_callback(message=None):
|
||||
"""Callback for display_instruction"""
|
||||
logging.info(f"""
|
||||
=== INSTRUCTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def self_reflection_callback(message=None):
|
||||
"""Callback for display_self_reflection"""
|
||||
logging.info(f"""
|
||||
=== SELF REFLECTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def generating_callback(content=None, elapsed_time=None):
|
||||
"""Callback for display_generating"""
|
||||
logging.info(f"""
|
||||
=== GENERATING ===
|
||||
Time: {datetime.now()}
|
||||
Content: {content}
|
||||
Elapsed Time: {elapsed_time}
|
||||
""")
|
||||
|
||||
# Register all callbacks
|
||||
register_display_callback('interaction', interaction_callback)
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
register_display_callback('instruction', instruction_callback)
|
||||
register_display_callback('self_reflection', self_reflection_callback)
|
||||
# register_display_callback('generating', generating_callback)
|
||||
|
||||
def task_callback(output):
|
||||
"""Callback for task completion"""
|
||||
logging.info(f"""
|
||||
=== TASK COMPLETED ===
|
||||
Time: {datetime.now()}
|
||||
Description: {output.description}
|
||||
Agent: {output.agent}
|
||||
Output: {output.raw[:200]}...
|
||||
""")
|
||||
|
||||
def internet_search_tool(query) -> list:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles and URLs.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
def main():
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
tools=[internet_search_tool],
|
||||
llm="gpt-4o",
|
||||
markdown=True,
|
||||
reflect_llm="gpt-4o",
|
||||
min_reflect=2,
|
||||
max_reflect=4
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
verbose=True,
|
||||
allow_delegation=True,
|
||||
llm="gpt-4o",
|
||||
tools=[],
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks with callbacks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher,
|
||||
tools=[internet_search_tool],
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.""",
|
||||
expected_output="A blog post of at least 4 paragraphs",
|
||||
agent=writer,
|
||||
context=[task1],
|
||||
callback=task_callback,
|
||||
tools=[]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="json_task",
|
||||
description="""Create a json object with a title of "My Task" and content of "My content".""",
|
||||
expected_output="""JSON output with title and content""",
|
||||
agent=researcher,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="save_output_task",
|
||||
description="""Save the AI blog post to a file""",
|
||||
expected_output="""File saved successfully""",
|
||||
agent=writer,
|
||||
context=[task2],
|
||||
output_file='test.txt',
|
||||
create_directory=True,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
# Create and run agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=True,
|
||||
process="sequential",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
## Async Callbacks
|
||||
|
||||
Async callbacks allow you to handle events asynchronously, which is particularly useful for long-running operations or when dealing with multiple agents simultaneously.
|
||||
|
||||
### Basic Async Callback Implementation
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import register_display_callback
|
||||
|
||||
async def async_interaction_callback(message=None, response=None, **kwargs):
|
||||
"""Async callback for handling interactions"""
|
||||
await asyncio.sleep(0) # Non-blocking pause
|
||||
print(f"Async processing - Message: {message}")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Register the async callback
|
||||
register_display_callback('interaction', async_interaction_callback)
|
||||
```
|
||||
|
||||
### Complete Async Example
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, register_display_callback
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
# Setup async logging
|
||||
async def setup_async_logging():
|
||||
logging.basicConfig(
|
||||
filename='async_ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Async callbacks
|
||||
async def async_interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
await asyncio.sleep(0)
|
||||
logging.info(f"""
|
||||
=== ASYNC INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
""")
|
||||
|
||||
async def async_error_callback(message=None):
|
||||
await asyncio.sleep(0)
|
||||
logging.error(f"""
|
||||
=== ASYNC ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
# Register async callbacks
|
||||
register_display_callback('interaction', async_interaction_callback, is_async=True)
|
||||
register_display_callback('error', async_error_callback, is_async=True)
|
||||
|
||||
# Create async task callback
|
||||
async def async_task_callback(output):
|
||||
await asyncio.sleep(0)
|
||||
logging.info(f"""
|
||||
=== ASYNC TASK COMPLETED ===
|
||||
Time: {datetime.now()}
|
||||
Description: {output.description}
|
||||
Agent: {output.agent}
|
||||
Output: {output.raw[:200]}...
|
||||
""")
|
||||
|
||||
async def main():
|
||||
await setup_async_logging()
|
||||
|
||||
# Create agent with async capabilities
|
||||
agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Assistant",
|
||||
goal="Demonstrate async callbacks",
|
||||
backstory="I am an async-capable assistant",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create task with async callback
|
||||
task = Task(
|
||||
name="async_task",
|
||||
description="Demonstrate async callbacks",
|
||||
agent=agent,
|
||||
expected_output="Async demonstration complete",
|
||||
callback=async_task_callback
|
||||
)
|
||||
|
||||
# Create and run agents with async support
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
await agents.start_async()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
### Available Async Functions
|
||||
|
||||
PraisonAI Agents provides several async versions of display functions, prefixed with 'a'. Here's the complete list:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="adisplay_interaction" icon="comments">
|
||||
```python
|
||||
async def adisplay_interaction(
|
||||
message,
|
||||
response,
|
||||
markdown=True,
|
||||
generation_time=None,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version of display_interaction for showing conversations.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_self_reflection" icon="brain">
|
||||
```python
|
||||
async def adisplay_self_reflection(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for displaying agent's self-reflection moments.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_instruction" icon="list-check">
|
||||
```python
|
||||
async def adisplay_instruction(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for showing instructions.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_tool_call" icon="wrench">
|
||||
```python
|
||||
async def adisplay_tool_call(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for displaying tool calls.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_error" icon="triangle-exclamation">
|
||||
```python
|
||||
async def adisplay_error(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for error messages.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_generating" icon="spinner">
|
||||
```python
|
||||
async def adisplay_generating(
|
||||
content: str = "",
|
||||
start_time: Optional[float] = None
|
||||
)
|
||||
```
|
||||
Async version for showing generation progress.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
#### Example Usage
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import (
|
||||
adisplay_interaction,
|
||||
adisplay_error,
|
||||
adisplay_tool_call
|
||||
)
|
||||
|
||||
async def main():
|
||||
# Display an interaction
|
||||
await adisplay_interaction(
|
||||
message="What's the weather?",
|
||||
response="Let me check that for you.",
|
||||
generation_time=0.5
|
||||
)
|
||||
|
||||
# Display a tool call
|
||||
await adisplay_tool_call(
|
||||
"Calling weather API for location data..."
|
||||
)
|
||||
|
||||
# Handle an error
|
||||
try:
|
||||
raise Exception("API connection failed")
|
||||
except Exception as e:
|
||||
await adisplay_error(str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Best Practices for Async Callbacks
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error Handling">
|
||||
Implement proper error handling in async callbacks:
|
||||
```python
|
||||
async def safe_async_callback(message=None, **kwargs):
|
||||
try:
|
||||
await asyncio.sleep(0)
|
||||
# Process the callback
|
||||
await process_message(message)
|
||||
except Exception as e:
|
||||
logging.error(f"Async callback error: {e}")
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Performance">
|
||||
Optimize async callbacks for better performance:
|
||||
```python
|
||||
async def optimized_async_callback(message=None, **kwargs):
|
||||
# Use asyncio.gather for concurrent operations
|
||||
results = await asyncio.gather(
|
||||
process_message(message),
|
||||
update_status(),
|
||||
log_interaction(message)
|
||||
)
|
||||
return results
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Key Considerations
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Concurrency" icon="arrows-split-up-and-left">
|
||||
- Use asyncio.gather for parallel operations
|
||||
- Avoid blocking calls in async callbacks
|
||||
- Handle concurrent access to shared resources
|
||||
</Card>
|
||||
<Card title="Resource Management" icon="server">
|
||||
- Implement proper cleanup in async contexts
|
||||
- Use async context managers when appropriate
|
||||
- Monitor memory usage in long-running callbacks
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
When using async callbacks, ensure all dependent operations are also async-compatible to prevent blocking the event loop.
|
||||
</Note>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Callback Not Firing" icon="bug">
|
||||
- Verify callback registration
|
||||
- Check verbose mode is enabled
|
||||
- Ensure correct callback name
|
||||
</Card>
|
||||
<Card title="Logging Issues" icon="file-lines">
|
||||
- Check file permissions
|
||||
- Verify logging configuration
|
||||
- Monitor log file size
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Async Callbacks" icon="bolt" href="./async">
|
||||
Learn about asynchronous callbacks
|
||||
</Card>
|
||||
<Card title="Advanced Patterns" icon="code" href="./advanced">
|
||||
Explore advanced callback patterns
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Remember to handle callbacks efficiently and implement proper error handling to ensure smooth agent operations.
|
||||
</Note>
|
||||
@@ -0,0 +1,239 @@
|
||||
---
|
||||
title: "Reasoning AI Agents"
|
||||
sidebarTitle: "Reasoning"
|
||||
description: "Reasoning enables AI agents to think logically, solve complex problems autonomously, and make human-like decisions through multi-step logical reasoning."
|
||||
icon: "brain-circuit"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/KNDVWGN3TpM"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
Reasoning in PraisonAI agents enables:
|
||||
- Autonomous problem solving
|
||||
- Multi-step logical reasoning
|
||||
- Human-like decision making
|
||||
- Deep comprehension of tasks
|
||||
- Error handling with alternative solutions
|
||||
|
||||
## Usage
|
||||
|
||||
Reasoning is controlled through reflection cycles using `min_reflect` and `max_reflect` parameters:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="SystemOps",
|
||||
role="System Administrator",
|
||||
goal="Manage and monitor system operations",
|
||||
backstory="You are an expert system administrator",
|
||||
min_reflect=6, # Minimum reflection cycles
|
||||
max_reflect=10 # Maximum reflection cycles
|
||||
)
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Deep Comprehension**: Instead of rule-based responses, agents understand tasks deeply
|
||||
- **Error Recovery**: Agents can reason through errors and find alternative solutions
|
||||
- **Step-by-Step Processing**: Complex tasks are broken down and processed systematically
|
||||
- **Quality Control**: Multiple reflection cycles ensure high-quality outputs
|
||||
- **Adaptive Problem Solving**: Agents can adjust their approach based on reasoning
|
||||
|
||||
## Example
|
||||
|
||||
Here's a complete example showing reasoning in action:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def run_terminal_command(command: str):
|
||||
"""
|
||||
Run a terminal command and return its output.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
print(f"Command output: {result}")
|
||||
return {"stdout": result.stdout, "stderr": result.stderr}
|
||||
except subprocess.CalledProcessError as e:
|
||||
return {"error": str(e), "stdout": e.stdout, "stderr": e.stderr}
|
||||
|
||||
def save_to_file(file_path: str, content: str):
|
||||
"""
|
||||
Save the given content to the specified file path. Create the folder/file if it doesn't exist.
|
||||
"""
|
||||
# Ensure the directory exists
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
# Write the content to the file
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(content)
|
||||
|
||||
return file_path
|
||||
|
||||
# Create System Operations Agent
|
||||
system_ops_agent = Agent(
|
||||
name="SystemOps",
|
||||
role="System Operations Specialist",
|
||||
goal="Execute and manage complex system operations and commands",
|
||||
backstory="""You are an expert system administrator with deep knowledge of Unix/Linux systems.
|
||||
You excel at running complex system commands, managing processes, and handling system operations.
|
||||
You always validate commands before execution and ensure they are safe to run.""",
|
||||
min_reflect=6,
|
||||
max_reflect=10,
|
||||
tools=[run_terminal_command, save_to_file],
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
# Create a complex task that tests various system operations
|
||||
task = Task(
|
||||
name="system_analysis_task",
|
||||
description="""Perform a comprehensive system analysis by executing the following operations in sequence:
|
||||
1. Get system information (OS, kernel version)
|
||||
2. List 5 running processes and sort them by CPU usage
|
||||
3. Check disk space usage and list directories over 1GB
|
||||
4. Display current system load and memory usage
|
||||
5. List 5 network connections
|
||||
6. Create a summary report with all findings in a text file called system_report.txt
|
||||
|
||||
Do it step by step. One task at a time.
|
||||
Save only the Summary report in the file.
|
||||
Use appropriate commands for each step and ensure proper error handling.""",
|
||||
expected_output="A comprehensive system report containing all requested information saved in system_report.txt",
|
||||
agent=system_ops_agent,
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[system_ops_agent],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
## e2b Tool Integration Example
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs
|
||||
import json
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
def code_interpret(code: str):
|
||||
"""
|
||||
A function to demonstrate running Python code dynamically using e2b_code_interpreter.
|
||||
"""
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
|
||||
# 1) Create Agents
|
||||
web_scraper_agent = Agent(
|
||||
name="WebScraper",
|
||||
role="Web Scraper",
|
||||
goal="Extract URLs from https://quotes.toscrape.com/",
|
||||
backstory="An expert in data extraction from websites, adept at navigating and retrieving detailed information.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
url_data_extractor_agent = Agent(
|
||||
name="URLDataExtractor",
|
||||
role="URL Data Extractor",
|
||||
goal="Crawl each URL for data extraction",
|
||||
backstory="Specializes in crawling websites to gather comprehensive data, ensuring nothing is missed from each link.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
blog_writer_agent = Agent(
|
||||
name="BlogWriter",
|
||||
role="Creative Content Writer",
|
||||
goal="Create engaging and insightful blog posts from provided data",
|
||||
backstory="An experienced content creator and storyteller with a knack for weaving compelling narratives. Skilled at analyzing quotes and creating meaningful connections that resonate with readers.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# 2) Create Tasks
|
||||
task_url_extraction = Task(
|
||||
name="url_extraction_task",
|
||||
description="""Use code_interpret to run Python code that fetches https://quotes.toscrape.com/
|
||||
and extracts 5 URLs from the page, then outputs them as a list. Only first 5 urls""",
|
||||
expected_output="A list of URLs extracted from the source page.",
|
||||
agent=web_scraper_agent,
|
||||
output_file="urls.txt"
|
||||
)
|
||||
|
||||
task_data_extraction = Task(
|
||||
name="data_extraction_task",
|
||||
description="""Take the URLs from url_extraction_task, crawl each URL and extract all pertinent
|
||||
data using code_interpret to run Python code, then output raw txt, not the html.""",
|
||||
expected_output="Raw data collected from each crawled URL.",
|
||||
agent=url_data_extractor_agent,
|
||||
context=[task_url_extraction]
|
||||
)
|
||||
|
||||
blog_writing_task = Task(
|
||||
name="blog_writing_task",
|
||||
description="""Write an engaging blog post using the extracted quotes data. The blog post should:
|
||||
1. Have a catchy title
|
||||
2. Include relevant quotes from the data
|
||||
3. Provide commentary and insights about the quotes
|
||||
4. Be well-structured with introduction, body, and conclusion
|
||||
5. Be approximately 500 words long""",
|
||||
expected_output="A well-written blog post incorporating the extracted quotes with analysis",
|
||||
agent=blog_writer_agent,
|
||||
context=[task_data_extraction],
|
||||
output_file="blog_post.txt"
|
||||
)
|
||||
|
||||
# 3) Create and run Agents manager
|
||||
agents_manager = PraisonAIAgents(
|
||||
agents=[web_scraper_agent, url_data_extractor_agent, blog_writer_agent],
|
||||
tasks=[task_url_extraction, task_data_extraction, blog_writing_task],
|
||||
verbose=True,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents_manager.start()
|
||||
```
|
||||
|
||||
## Integration with Tools
|
||||
|
||||
Reasoning works particularly well with tools that require complex decision-making:
|
||||
|
||||
- **Code Interpreter**: For dynamic code generation and execution
|
||||
- **System Operations**: For multi-step system management tasks
|
||||
- **Data Analysis**: For complex data processing workflows
|
||||
- **Web Scraping**: For intelligent data extraction and processing
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Higher reflection cycles mean more thorough reasoning but longer processing time
|
||||
- `min_reflect` ensures minimum quality standards
|
||||
- `max_reflect` prevents excessive processing
|
||||
- Balance based on task complexity and quality requirements
|
||||
@@ -0,0 +1,102 @@
|
||||
---
|
||||
title: "Self Reflection AI Agents"
|
||||
sidebarTitle: "Self-Reflection"
|
||||
description: "Self-reflection is a powerful feature in PraisonAI that enables agents to evaluate and improve their own responses before delivering them. This leads to higher quality outputs and more reliable task completion."
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/vLXobEN2Vc8"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
When an agent with self-reflection enabled processes a task:
|
||||
1. It generates an initial response using its tools and capabilities
|
||||
2. The agent then reflects on its own response, evaluating:
|
||||
- Completeness
|
||||
- Accuracy
|
||||
- Relevance
|
||||
- Quality
|
||||
3. Based on this reflection, the agent may revise and improve its response
|
||||
4. This cycle can repeat until the agent is satisfied with the quality
|
||||
|
||||
## Usage
|
||||
|
||||
Self-reflection is enabled by default for all agents. You can explicitly control it using the `self_reflect` parameter:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at analyzing tech trends",
|
||||
self_reflect=True # Enable self-reflection (default)
|
||||
)
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Higher Quality Outputs**: Agents can catch and correct potential issues before delivering responses
|
||||
- **More Reliable Task Completion**: Self-reflection helps ensure all aspects of a task are properly addressed
|
||||
- **Conscious Decision Making**: Agents evaluate their own work, leading to more thoughtful responses
|
||||
- **Improved Accuracy**: Multiple reflection cycles help refine and perfect the output
|
||||
|
||||
## Integration with Processes
|
||||
|
||||
Self-reflection works seamlessly with both sequential and hierarchical processes:
|
||||
|
||||
- **Sequential**: Each agent self-reflects on their individual tasks
|
||||
- **Hierarchical**: Agents self-reflect before reporting to the manager agent, ensuring high-quality inputs for decision-making
|
||||
|
||||
## Example
|
||||
|
||||
Here's a complete example showing self-reflection in action:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at analyzing tech trends",
|
||||
self_reflect=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report on AI trends",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
In this example, the researcher agent will:
|
||||
1. Research AI advancements
|
||||
2. Generate an initial report
|
||||
3. Self-reflect on the report's quality
|
||||
4. Make improvements if needed
|
||||
5. Deliver the final, refined output
|
||||
|
||||
## Performance Impact
|
||||
|
||||
While self-reflection adds additional processing time, the improvement in output quality often justifies the extra computation.
|
||||
The number of reflection cycles need to be manually optimized to balance quality and performance.
|
||||
@@ -1,6 +1,20 @@
|
||||
---
|
||||
title: "Firecrawl PraisonAI Integration"
|
||||
description: "Guide for integrating Firecrawl web scraping capabilities with PraisonAI, including custom tool implementation for web page content extraction"
|
||||
icon: "spider"
|
||||
---
|
||||
|
||||
# Firecrawl PraisonAI Integration
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/UoqUDcLcOYo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/UoqUDcLcOYo"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Firecrawl running in Localhost:3002
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
title: "AutoGen with PraisonAI"
|
||||
description: "Guide for using AutoGen framework with PraisonAI, including installation, setup, and multi-agent conversation capabilities"
|
||||
icon: "robot"
|
||||
---
|
||||
|
||||
# AutoGen with PraisonAI
|
||||
|
||||
Low-code solution to run AutoGen with integrated tools and features.
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
title: "CrewAI with PraisonAI"
|
||||
description: "Guide for using CrewAI framework with PraisonAI, including installation, setup, and execution of agent-based tasks"
|
||||
icon: "users"
|
||||
---
|
||||
|
||||
# CrewAI with PraisonAI
|
||||
|
||||
Low-code solution to run CrewAI with integrated tools and features.
|
||||
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: "Multimodal AI Agents"
|
||||
description: "Guide for creating and using multimodal AI agents in PraisonAI for processing images, videos, and other media types"
|
||||
icon: "images"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/hjAWmUT1qqY"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
# Multimodal AI Agents
|
||||
|
||||
PraisonAI supports multimodal AI agents capable of processing various types of media including images and videos. This enables you to create agents that can understand and analyze visual content alongside text.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create `multimodal_app.py` and add the following code:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create Vision Analysis Agent
|
||||
vision_agent = Agent(
|
||||
name="VisionAnalyst",
|
||||
role="Computer Vision Specialist",
|
||||
goal="Analyze images and videos to extract meaningful information",
|
||||
backstory="""You are an expert in computer vision and image analysis.
|
||||
You excel at describing images, detecting objects, and understanding visual content.""",
|
||||
llm="gpt-4o-mini",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create tasks with different media types
|
||||
task = Task(
|
||||
name="analyze_landmark",
|
||||
description="Describe this famous landmark and its architectural features.",
|
||||
expected_output="Detailed description of the landmark's architecture and significance",
|
||||
agent=vision_agent,
|
||||
images=["https://upload.wikimedia.org/wikipedia/commons/b/bf/Krakow_-_Kosciol_Mariacki.jpg"]
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[vision_agent],
|
||||
tasks=[task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
print(result)
|
||||
```
|
||||
|
||||
## Agent Configuration
|
||||
|
||||
### Core Attributes
|
||||
- All standard agent attributes apply (role, goal, backstory, etc.)
|
||||
- `llm`: Must be a model that supports vision capabilities (e.g., "gpt-4o-mini")
|
||||
- `verbose`: Enable detailed logs (default: False)
|
||||
|
||||
## Task Configuration
|
||||
|
||||
### Media Support
|
||||
Tasks can include various types of media through the `images` parameter:
|
||||
|
||||
1. **Image URLs**
|
||||
```python
|
||||
task = Task(
|
||||
description="Analyze the image",
|
||||
images=["https://example.com/image.jpg"]
|
||||
)
|
||||
```
|
||||
|
||||
2. **Local Image Files**
|
||||
```python
|
||||
task = Task(
|
||||
description="Analyze the local image",
|
||||
images=["path/to/local/image.jpg"]
|
||||
)
|
||||
```
|
||||
|
||||
3. **Video Files**
|
||||
```python
|
||||
task = Task(
|
||||
description="Analyze the video content",
|
||||
images=["path/to/video.mp4"]
|
||||
)
|
||||
```
|
||||
|
||||
### Task Types
|
||||
|
||||
1. **Image Analysis**
|
||||
- Object detection
|
||||
- Scene description
|
||||
- Architectural analysis
|
||||
- Text extraction from images
|
||||
|
||||
2. **Video Analysis**
|
||||
- Event summarization
|
||||
- Object tracking
|
||||
- Action recognition
|
||||
- Text and caption extraction
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Multiple Media Sources
|
||||
Tasks can process multiple media sources simultaneously:
|
||||
|
||||
```python
|
||||
task = Task(
|
||||
description="Compare these images and describe the differences",
|
||||
images=[
|
||||
"https://example.com/image1.jpg",
|
||||
"https://example.com/image2.jpg"
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
### Combining Text and Visual Analysis
|
||||
Create tasks that leverage both text and visual understanding:
|
||||
|
||||
```python
|
||||
task = Task(
|
||||
description="""Analyze this technical diagram and:
|
||||
1. Explain the components
|
||||
2. Describe their relationships
|
||||
3. Identify any text or labels
|
||||
4. Provide technical insights""",
|
||||
images=["diagram.jpg"]
|
||||
)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Media Handling**
|
||||
- Ensure images are in supported formats (JPEG, PNG, etc.)
|
||||
- Keep video files within reasonable size limits
|
||||
- Provide clear, high-quality media for best results
|
||||
|
||||
2. **Task Design**
|
||||
- Write clear, specific descriptions
|
||||
- Break complex analyses into subtasks
|
||||
- Include expected output format
|
||||
|
||||
3. **Performance Optimization**
|
||||
- Use appropriate model versions for your needs
|
||||
- Consider caching for repeated analyses
|
||||
- Monitor token usage with visual content
|
||||
|
||||
4. **Error Handling**
|
||||
- Validate media files before processing
|
||||
- Handle missing or corrupted files gracefully
|
||||
- Implement retry logic for failed analyses
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
1. **Document Analysis**
|
||||
```python
|
||||
document_task = Task(
|
||||
description="Extract and summarize text from this document image",
|
||||
expected_output="Structured text content with key information highlighted",
|
||||
agent=vision_agent,
|
||||
images=["document.jpg"]
|
||||
)
|
||||
```
|
||||
|
||||
2. **Security Monitoring**
|
||||
```python
|
||||
security_task = Task(
|
||||
description="Monitor this security camera feed and report any suspicious activity",
|
||||
expected_output="Detailed report of detected events and anomalies",
|
||||
agent=vision_agent,
|
||||
images=["security_feed.mp4"]
|
||||
)
|
||||
```
|
||||
|
||||
3. **Medical Imaging**
|
||||
```python
|
||||
medical_task = Task(
|
||||
description="Analyze this medical scan and identify any abnormalities",
|
||||
expected_output="Professional medical image analysis report",
|
||||
agent=vision_agent,
|
||||
images=["medical_scan.jpg"]
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,207 @@
|
||||
---
|
||||
title: "PraisonAI Agents"
|
||||
description: "Guide for using PraisonAI Agents framework, a lightweight package for creating and managing AI agents with advanced capabilities"
|
||||
icon: "users-gear"
|
||||
---
|
||||
|
||||
A lightweight package dedicated to creating and managing AI agents with advanced capabilities.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create `app.py` and add the following code:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
research_task = Task(
|
||||
description="Research the latest developments in AI and data science",
|
||||
expected_output="A comprehensive report on recent AI trends and breakthroughs",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
writing_task = Task(
|
||||
description="Create an engaging blog post about the research findings",
|
||||
expected_output="A well-structured blog post explaining AI developments",
|
||||
agent=writer,
|
||||
context=[research_task] # This task depends on research_task output
|
||||
)
|
||||
|
||||
# Create and run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[research_task, writing_task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
print(result)
|
||||
```
|
||||
|
||||
## Agent Configuration
|
||||
|
||||
### Core Attributes
|
||||
- `name`: Agent's identifier
|
||||
- `role`: Agent's function/expertise
|
||||
- `goal`: Individual objective
|
||||
- `backstory`: Context and personality
|
||||
- `llm`: Language model (default: OpenAI's GPT-4)
|
||||
- `verbose`: Enable detailed logs (default: False)
|
||||
- `markdown`: Enable markdown formatting (default: True)
|
||||
|
||||
### Optional Attributes
|
||||
- `tools`: List of available tools
|
||||
- `memory`: Enable conversation history (default: True)
|
||||
- `max_iter`: Maximum iterations (default: 20)
|
||||
- `max_rpm`: Rate limit for API calls
|
||||
- `allow_delegation`: Enable task delegation (default: False)
|
||||
|
||||
## Task Configuration
|
||||
|
||||
### Core Attributes
|
||||
- `description`: Task details
|
||||
- `expected_output`: Desired outcome
|
||||
- `agent`: Assigned agent
|
||||
|
||||
### Optional Attributes
|
||||
- `context`: Dependencies on other tasks
|
||||
- `tools`: Task-specific tools
|
||||
- `async_execution`: Run asynchronously (default: False)
|
||||
- `output_file`: Save output to file
|
||||
- `callback`: Post-task function
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Tool Integration
|
||||
```python
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
def search_tool(query: str) -> list:
|
||||
"""
|
||||
Perform a web search using DuckDuckGo and return relevant results.
|
||||
|
||||
Args:
|
||||
query (str): The search query string to look up information about.
|
||||
|
||||
Returns:
|
||||
list: A list of dictionaries containing search results with the following keys:
|
||||
- title (str): The title of the search result
|
||||
- url (str): The URL of the search result
|
||||
- snippet (str): A brief excerpt or description of the search result
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", ""),
|
||||
})
|
||||
return results
|
||||
|
||||
agent = Agent(
|
||||
name="Researcher",
|
||||
tools=[search_tool]
|
||||
)
|
||||
```
|
||||
|
||||
### Custom Callbacks
|
||||
```python
|
||||
def task_completed(output):
|
||||
print(f"Task completed: {output.description}")
|
||||
print(f"Output: {output.raw}")
|
||||
|
||||
task = Task(
|
||||
description="Analysis task",
|
||||
callback=task_completed
|
||||
)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The framework includes built-in error handling for:
|
||||
- API rate limits
|
||||
- Token limits
|
||||
- Task timeouts
|
||||
- Tool execution failures
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Agent Design**
|
||||
- Give clear, specific roles and goals
|
||||
- Provide detailed backstories
|
||||
- Use appropriate tools for tasks
|
||||
|
||||
2. **Task Management**
|
||||
- Break complex tasks into subtasks
|
||||
- Set clear dependencies
|
||||
- Use async execution for independent tasks
|
||||
|
||||
3. **Resource Optimization**
|
||||
- Enable caching when appropriate
|
||||
- Set reasonable max_iter limits
|
||||
- Use rate limiting for API calls
|
||||
|
||||
4. **Error Handling**
|
||||
- Implement task callbacks
|
||||
- Set appropriate timeouts
|
||||
- Monitor execution logs
|
||||
|
||||
### Parallel Execution (Upcoming)
|
||||
```python
|
||||
task1 = Task(
|
||||
description="Research task 1",
|
||||
async_execution=True
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
description="Research task 2",
|
||||
async_execution=True
|
||||
)
|
||||
|
||||
final_task = Task(
|
||||
description="Compile results",
|
||||
context=[task1, task2] # Waits for both tasks
|
||||
)
|
||||
```
|
||||
|
||||
### Memory Management (Upcoming)
|
||||
```python
|
||||
agent = Agent(
|
||||
name="Analyst",
|
||||
memory=True, # Enable memory
|
||||
memory_config={
|
||||
"type": "short_term",
|
||||
"max_tokens": 4000
|
||||
}
|
||||
)
|
||||
```
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
# Home
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Fn1lQjC0GO0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="/logo/dark.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="/logo/light.png" />
|
||||
<img alt="PraisonAI Logo" src="/logo/light.png" style={{display: "block", margin: "auto"}} />
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/MervinPraison/PraisonAI"><img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" /></a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI"><img src="https://img.shields.io/github/v/release/MervinPraison/PraisonAI" alt="Latest Stable Version" /></a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License" /></a>
|
||||
</p>
|
||||
|
||||
# Praison AI
|
||||
|
||||
Praison AI, leveraging both AutoGen and CrewAI or any other agent framework, represents a low-code, centralised framework designed to simplify the creation and orchestration of multi-agent systems for various LLM applications, emphasizing ease of use, customization, and human-agent interaction.
|
||||
|
||||
<div align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="images/architecture-dark.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="images/architecture-light.png" />
|
||||
<img alt="PraisonAI Architecture" src="images/architecture-light.png" />
|
||||
</picture>
|
||||
</div>
|
||||
|
||||
## Different User Interfaces:
|
||||
|
||||
| Interface | Description | URL |
|
||||
|---|---|---|
|
||||
| **UI** | Multi Agents such as CrewAI or AutoGen | [https://docs.praison.ai/ui/ui](https://docs.praison.ai/ui/ui) |
|
||||
| **Chat** | Chat with 100+ LLMs, single AI Agent | [https://docs.praison.ai/ui/chat](https://docs.praison.ai/ui/chat) |
|
||||
| **Code** | Chat with entire Codebase, single AI Agent | [https://docs.praison.ai/ui/code](https://docs.praison.ai/ui/code) |
|
||||
|
||||
## Google Colab Multi Agents
|
||||
|
||||
| | Cookbook | Open in Colab |
|
||||
| ------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Basic | PraisonAI | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
|
||||
| Include Tools | PraisonAI Tools | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
|
||||
|
||||
## Installation Options
|
||||
|
||||
### Basic Installation
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
|
||||
### Framework-specific Installation
|
||||
```bash
|
||||
# Install with CrewAI support
|
||||
pip install "praisonai[crewai]"
|
||||
|
||||
# Install with AutoGen support
|
||||
pip install "praisonai[autogen]"
|
||||
|
||||
# Install with both frameworks
|
||||
pip install "praisonai[crewai,autogen]"
|
||||
```
|
||||
|
||||
### UI and Additional Features
|
||||
```bash
|
||||
pip install "praisonai[ui]" # UI support
|
||||
pip install "praisonai[chat]" # Chat interface
|
||||
pip install "praisonai[code]" # Code interface
|
||||
pip install "praisonai[realtime]" # Realtime voice interaction
|
||||
pip install "praisonai[call]" # Call feature
|
||||
```
|
||||
|
||||
## TL;DR Multi Agents
|
||||
|
||||
```bash
|
||||
pip install praisonai
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
praisonai --init create a movie script about dog in moon
|
||||
praisonai
|
||||
```
|
||||
|
||||
## Initialise
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
```
|
||||
|
||||
Generate your OPENAI API KEY from here: https://platform.openai.com/api-keys
|
||||
|
||||
Note: You can use other providers such as Ollama, Mistral ... etc. Details are provided at the bottom.
|
||||
|
||||
```bash
|
||||
praisonai --init create a movie script about dog in moon
|
||||
```
|
||||
This will automatically create agents.yaml file in the current directory.
|
||||
|
||||
### To initialse with a specific agent framework (Optional):
|
||||
|
||||
```bash
|
||||
praisonai --framework autogen --init create movie script about cat in mars
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
praisonai
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
python -m praisonai
|
||||
```
|
||||
|
||||
### Specify the agent framework (Optional):
|
||||
|
||||
```bash
|
||||
praisonai --framework autogen
|
||||
```
|
||||
|
||||
### Full Automatic Mode
|
||||
|
||||
```bash
|
||||
praisonai --auto create a movie script about Dog in Moon
|
||||
```
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
---
|
||||
title: "Praison AI"
|
||||
sidebarTitle: "Home"
|
||||
description: "Comprehensive guide to PraisonAI - an AI Agents Framework with Self Reflection, combining PraisonAI Agents, AutoGen, and CrewAI for building multi-agent LLM systems"
|
||||
icon: "house"
|
||||
openGraph:
|
||||
url: "/"
|
||||
seo:
|
||||
canonical: "/"
|
||||
---
|
||||
<Note>
|
||||
Welcome to PraisonAI - Your comprehensive solution for building and managing multi-agent LLM systems with self-reflection capabilities.
|
||||
</Note>
|
||||
<div className="flex justify-start w-full max-w-xs sm:max-w-sm md:max-w-md">
|
||||
<img
|
||||
src="images/praisonai-logo-black.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto rounded-lg shadow-md block dark:hidden"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
<img
|
||||
src="images/praisonai-logo-light.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto rounded-lg shadow-md hidden dark:block"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-4 my-8">
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/v/release/MervinPraison/PraisonAI" alt="Latest Stable Version" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/stars/MervinPraison/PraisonAI?style=social" alt="GitHub Stars" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/forks/MervinPraison/PraisonAI?style=social" alt="GitHub Forks" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tip>
|
||||
PraisonAI combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration.
|
||||
</Tip>
|
||||
|
||||
## Key Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="AI Agents Creation" icon="robot">
|
||||
Automated creation and management of AI agents with self-reflection capabilities
|
||||
</Card>
|
||||
<Card title="Framework Integration" icon="puzzle-piece">
|
||||
Seamless integration with CrewAI and AutoGen frameworks
|
||||
</Card>
|
||||
<Card title="LLM Support" icon="brain">
|
||||
Support for 100+ Language Learning Models
|
||||
</Card>
|
||||
<Card title="Code Integration" icon="code">
|
||||
Chat with your entire codebase using advanced context understanding
|
||||
</Card>
|
||||
<Card title="Interactive UI" icon="desktop">
|
||||
Rich, interactive user interfaces for better control and monitoring
|
||||
</Card>
|
||||
<Card title="Configuration" icon="gear">
|
||||
YAML-based configuration for easy setup and customization
|
||||
</Card>
|
||||
<Card title="Tool Integration" icon="screwdriver-wrench">
|
||||
Custom tool integration for extended functionality
|
||||
</Card>
|
||||
<Card title="Search Capability" icon="magnifying-glass">
|
||||
Internet search using Crawl4AI and Tavily
|
||||
</Card>
|
||||
</CardGroup>
|
||||
<br />
|
||||
<div className="relative w-full aspect-video overflow-hidden rounded-lg shadow-lg mb-8">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full border-0"
|
||||
src="https://www.youtube.com/embed/Fn1lQjC0GO0"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
style={{
|
||||
maxWidth: '100vw',
|
||||
margin: '0 auto'
|
||||
}}
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Installation Options
|
||||
|
||||
<Tabs>
|
||||
<Tab title="No Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Auto Mode">
|
||||
```bash
|
||||
praisonai --auto create a movie script about Robots in Mars
|
||||
```
|
||||
|
||||
This will automatically create required agents and complete the task
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.py` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create multiple agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="You are a content strategist",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Define multiple tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="Create a blog post about AI advancements",
|
||||
expected_output="A blog post",
|
||||
agent=writer
|
||||
)
|
||||
|
||||
# Run with hierarchical process
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
verbose=False,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Integration Options
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ollama Integration">
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Groq Integration">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Logging Configuration">
|
||||
```bash
|
||||
# Basic logging
|
||||
export LOGLEVEL=info
|
||||
|
||||
# Advanced logging
|
||||
export LOGLEVEL=debug
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Use Cases
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Customer Service" icon="headset">
|
||||
Build intelligent support agents that can handle customer inquiries and resolve issues autonomously.
|
||||
</Card>
|
||||
<Card title="Data Analysis" icon="chart-line">
|
||||
Create agents that can process, analyze, and derive insights from complex datasets.
|
||||
</Card>
|
||||
<Card title="Content Creation" icon="pen-nib">
|
||||
Deploy agents that can generate, edit, and optimize content across various formats.
|
||||
</Card>
|
||||
<Card title="Process Automation" icon="gears">
|
||||
Automate complex workflows with intelligent agents that can coordinate and execute tasks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Praison AI Package Overall Features
|
||||
|
||||
<Frame caption="PraisonAI Features Overview">
|
||||
<div className="w-full max-w-4xl mx-auto">
|
||||
<img
|
||||
src="images/architecture-light.png"
|
||||
alt="PraisonAI Features"
|
||||
className="w-full h-auto rounded-lg shadow-lg block dark:hidden"
|
||||
width="1200"
|
||||
height="800"
|
||||
/>
|
||||
<img
|
||||
src="images/architecture-dark.png"
|
||||
alt="PraisonAI Features"
|
||||
className="w-full h-auto rounded-lg shadow-lg hidden dark:block"
|
||||
width="1200"
|
||||
height="800"
|
||||
/>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Self-Reflection" icon="brain-circuit" href="/features/selfreflection">
|
||||
Agents that evaluate and improve their own responses for higher accuracy
|
||||
</Card>
|
||||
<Card title="Reasoning" icon="gears" href="/features/reasoning">
|
||||
Multi-step logical reasoning and autonomous problem solving
|
||||
</Card>
|
||||
<Card title="CrewAI Framework" icon="users-gear" href="/framework/crewai">
|
||||
Build collaborative AI teams with CrewAI integration
|
||||
</Card>
|
||||
<Card title="AutoGen Framework" icon="robot" href="/framework/autogen">
|
||||
Create autonomous agent networks using AutoGen
|
||||
</Card>
|
||||
<Card title="Multimodal Agents" icon="icons" href="/framework/multimodalagents">
|
||||
Work with agents that can process text, images, and other data types
|
||||
</Card>
|
||||
<Card title="Train" icon="graduation-cap" href="/train">
|
||||
Train and fine-tune your LLMs for specific tasks and domains. Then use it as an AI Agent.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## User Interfaces
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Multi Agents UI" icon="users" href="/ui/ui">
|
||||
Work with CrewAI or AutoGen multi-agent systems
|
||||
</Card>
|
||||
<Card title="Chat Interface" icon="comments" href="/ui/chat">
|
||||
Chat with 100+ LLMs using a single AI Agent
|
||||
</Card>
|
||||
<Card title="Code Interface" icon="code" href="/ui/code">
|
||||
Interact with your entire codebase
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Loaded 100 of 177 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user