Compare commits

..
660 changed files with 16044 additions and 141490 deletions

No files matched your search

-1885
View File
File diff suppressed because it is too large. Load diff
-6
View File
@@ -1,6 +0,0 @@
OPENAI_MODEL_NAME="gpt-4o"
OPENAI_API_KEY="Enter your API key"
OPENAI_API_BASE="https://api.openai.com/v1"
CHAINLIT_USERNAME=admin
CHAINLIT_USERNAME=admin
CHAINLIT_AUTH_SECRET="chainlit create-secret to create"
-10
View File
@@ -1,10 +0,0 @@
{
"extends": ["plugin:mdx/recommended"],
// optional, if you want to lint code blocks at the same time
"settings": {
"mdx/code-blocks": true,
// optional, if you want to disable language mapper, set it to `false`
// if you want to override the default language mapper inside, you can provide your own
"mdx/language-mapper": {}
}
}
-2
View File
@@ -1,2 +0,0 @@
patreon: MervinPraison
ko_fi: MervinPraison
-44
View File
@@ -1,44 +0,0 @@
name: Daily Publish Docker
on:
push:
branches:
- main
schedule:
- cron: '0 0 * * *'
jobs:
check-and-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Check last commit time
id: check_commit
run: |
last_commit_time=$(git log -1 --format=%ct)
current_time=$(date +%s)
time_diff=$((current_time - last_commit_time))
if [ $time_diff -ge 120 ] && [ $time_diff -lt 240 ]; then
echo "should_run=true" >> $GITHUB_OUTPUT
else
echo "should_run=false" >> $GITHUB_OUTPUT
fi
- name: Set up Docker Buildx
if: steps.check_commit.outputs.should_run == 'true'
uses: docker/setup-buildx-action@v1
- name: Log in to the GitHub Container Registry
if: steps.check_commit.outputs.should_run == 'true'
run: echo ${{ secrets.GH_TOKEN }} | docker login ghcr.io -u USERNAME --password-stdin
- name: Build and push Docker image
if: steps.check_commit.outputs.should_run == 'true'
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ghcr.io/mervinpraison/praisonai:latest
-40
View File
@@ -1,40 +0,0 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python package
on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
# - name: Lint with flake8
# run: |
# # stop the build if there are Python syntax errors or undefined names
# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
# - name: Test with pytest
# run: |
# pytest
-39
View File
@@ -1,39 +0,0 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Upload Python Package
on:
release:
types: [published]
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
-524
View File
@@ -1,524 +0,0 @@
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
-36
View File
@@ -1,36 +0,0 @@
name: Run specific unittest
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.11
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
export PATH="$HOME/.local/bin:$PATH"
- name: Install dependencies
run: |
poetry install
poetry run python -m pip install duckduckgo_search
- name: Set environment variables
run: |
echo "OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}" >> $GITHUB_ENV
echo "OPENAI_API_BASE=${{ secrets.OPENAI_API_BASE }}" >> $GITHUB_ENV
echo "OPENAI_MODEL_NAME=${{ secrets.OPENAI_MODEL_NAME }}" >> $GITHUB_ENV
- name: Run specific unittest
run: |
poetry run python -m unittest tests.test.TestExamples
+21 -67
View File
@@ -1,69 +1,23 @@
.vscode
crewai
.cache
__pycache__
chroma.sqlite3
test
dist
.env
assets
.idea
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.pytest_cache
praisonAI.egg-info
flagged
test.yaml
db
praisonai_prompt.txt
watch.sh
docs.sh
other
output
.env.local
.env.development.local
.env.test.local
.env.production.local
.files
threads.db
threads.db-journal
.chainlit
!praisonai/ui/config/.chainlit
site
# Ignore Sphinx build directory
docs/_build/
docs/source/
docs/build/
# Ignore Sphinx cache
docs/_build/doctrees/
docs/_build/doctrees/*
docs/_build/doctrees/.doctrees
# Ignore Sphinx logs and local build files
docs/_build/.buildinfo
docs/_build/.buildinfo/*
docs/_build/.buildinfo/.buildinfo
praisonai/doc
# agentops
trained_agents_data.pkl
agentops.log
# crewAI
crewAI
# virtualenv
.venv
# Credentials
credentials.json
# node_modules
node_modules
outputs
agents/praisonaiagents/build
agents/praisonaiagents/dist
agents/praisonaiagents/praisonaiagents.egg-info
.codegpt
.praison
npm-debug.log*
yarn-debug.log*
yarn-error.log*
-4
View File
@@ -1,4 +0,0 @@
# praisonai/ui/context.py
# /Users/praison/miniconda3/envs/praisonai-package/lib/python3.11/site-packages/llama_index/packs/code_hierarchy/code_hierarchy.py
praisonai/ui/components/aicoder.py
praisonai/ui/code.py
-4
View File
@@ -1,4 +0,0 @@
cookbooks
tests
docs
praisonai/inbuilt_tools/*
-3
View File
@@ -1,3 +0,0 @@
# praisonai/ui/context.py
# /Users/praison/miniconda3/envs/praisonai-package/lib/python3.11/site-packages/llama_index/packs/code_hierarchy/code_hierarchy.py
praisonai/setup
-23
View File
@@ -1,23 +0,0 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.12"
jobs:
post_install:
- bash docs/generate_docs.sh
mkdocs:
configuration: mkdocs.yml
fail_on_warning: true
python:
install:
- requirements: docs/requirements.txt
-20
View File
@@ -1,20 +0,0 @@
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+69 -566
View File
@@ -1,567 +1,70 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/logo/dark.png" />
<source media="(prefers-color-scheme: light)" srcset="docs/logo/light.png" />
<img alt="PraisonAI Logo" src="docs/logo/light.png" />
</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>
<div align="center">
# Praison AI
<a href="https://trendshift.io/repositories/9130" target="_blank"><img src="https://trendshift.io/api/badge/repositories/9130" alt="MervinPraison%2FPraisonAI | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
PraisonAI is a production-ready Multi-AI Agents framework with self-reflection, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. By integrating PraisonAI Agents, AutoGen, and CrewAI into a low-code solution, it streamlines the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective 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
- 📚 Add Custom Knowledge
- 🧠 Agents with Short and Long Term Memory
- 📄 Chat with PDF Agents
- 💻 Code Interpreter Agents
- 📚 RAG Agents
- 🤔 Async & Parallel Processing
- 🔄 Auto Agents
- 🔢 Math Agents
- 🎯 Structured Output Agents
- 🔗 LangChain Integrated Agents
- 📞 Callback Agents
- 🤏 Mini AI Agents
- 🛠️ 100+ Custom Tools
- 📄 YAML Configuration
- 💯 100+ LLM Support
## Using Code
Light weight package dedicated for coding:
```bash
pip install praisonaiagents
```
```bash
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
```
### 1. Single Agent
Create app.py file and add the code below:
```python
from praisonaiagents import Agent
agent = Agent(instructions="Your are a helpful AI assistant")
agent.chat("Write a movie script about a robot in Mars")
```
Run:
```bash
python app.py
```
### 2. Multi Agents
Create app.py file and add the code below:
```python
from praisonaiagents import Agent, PraisonAIAgents
research_agent = Agent(instructions="Research about AI")
summarise_agent = Agent(instructions="Summarise research agent's findings")
agents = PraisonAIAgents(agents=[research_agent, summarise_agent])
agents.start()
```
Run:
```bash
python app.py
```
## Using No Code
### Auto Mode:
```bash
pip install praisonai
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
praisonai --auto create a movie script about Robots in Mars
```
## AI Agents Flow
```mermaid
graph LR
%% Define the main flow
Start([▶ Start]) --> Agent1
Agent1 --> Process[⚙ Process]
Process --> Agent2
Agent2 --> Output([✓ Output])
Process -.-> Agent1
%% Define subgraphs for agents and their tasks
subgraph Agent1[ ]
Task1[📋 Task]
AgentIcon1[🤖 AI Agent]
Tools1[🔧 Tools]
Task1 --- AgentIcon1
AgentIcon1 --- Tools1
end
subgraph Agent2[ ]
Task2[📋 Task]
AgentIcon2[🤖 AI Agent]
Tools2[🔧 Tools]
Task2 --- AgentIcon2
AgentIcon2 --- Tools2
end
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Start,Output,Task1,Task2 input
class Process,AgentIcon1,AgentIcon2 process
class Tools1,Tools2 tools
class Agent1,Agent2 transparent
```
## AI Agents with Tools
Create AI agents that can use tools to interact with external systems and perform actions.
```mermaid
flowchart TB
subgraph Tools
direction TB
T3[Internet Search]
T1[Code Execution]
T2[Formatting]
end
Input[Input] ---> Agents
subgraph Agents
direction LR
A1[Agent 1]
A2[Agent 2]
A3[Agent 3]
end
Agents ---> Output[Output]
T3 --> A1
T1 --> A2
T2 --> A3
style Tools fill:#189AB4,color:#fff
style Agents fill:#8B0000,color:#fff
style Input fill:#8B0000,color:#fff
style Output fill:#8B0000,color:#fff
```
## AI Agents with Memory
Create AI agents with memory capabilities for maintaining context and information across tasks.
```mermaid
flowchart TB
subgraph Memory
direction TB
STM[Short Term]
LTM[Long Term]
end
subgraph Store
direction TB
DB[(Vector DB)]
end
Input[Input] ---> Agents
subgraph Agents
direction LR
A1[Agent 1]
A2[Agent 2]
A3[Agent 3]
end
Agents ---> Output[Output]
Memory <--> Store
Store <--> A1
Store <--> A2
Store <--> A3
style Memory fill:#189AB4,color:#fff
style Store fill:#2E8B57,color:#fff
style Agents fill:#8B0000,color:#fff
style Input fill:#8B0000,color:#fff
style Output fill:#8B0000,color:#fff
```
## AI Agents with Different Processes
### Sequential Process
The simplest form of task execution where tasks are performed one after another.
```mermaid
graph LR
Input[Input] --> A1
subgraph Agents
direction LR
A1[Agent 1] --> A2[Agent 2] --> A3[Agent 3]
end
A3 --> Output[Output]
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Input,Output input
class A1,A2,A3 process
class Agents transparent
```
### Hierarchical Process
Uses a manager agent to coordinate task execution and agent assignments.
```mermaid
graph TB
Input[Input] --> Manager
subgraph Agents
Manager[Manager Agent]
subgraph Workers
direction LR
W1[Worker 1]
W2[Worker 2]
W3[Worker 3]
end
Manager --> W1
Manager --> W2
Manager --> W3
end
W1 --> Manager
W2 --> Manager
W3 --> Manager
Manager --> Output[Output]
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Input,Output input
class Manager,W1,W2,W3 process
class Agents,Workers transparent
```
### Workflow Process
Advanced process type supporting complex task relationships and conditional execution.
```mermaid
graph LR
Input[Input] --> Start
subgraph Workflow
direction LR
Start[Start] --> C1{Condition}
C1 --> |Yes| A1[Agent 1]
C1 --> |No| A2[Agent 2]
A1 --> Join
A2 --> Join
Join --> A3[Agent 3]
end
A3 --> Output[Output]
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef decision fill:#2E8B57,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Input,Output input
class Start,A1,A2,A3,Join process
class C1 decision
class Workflow transparent
```
#### Agentic Routing Workflow
Create AI agents that can dynamically route tasks to specialized LLM instances.
```mermaid
flowchart LR
In[In] --> Router[LLM Call Router]
Router --> LLM1[LLM Call 1]
Router --> LLM2[LLM Call 2]
Router --> LLM3[LLM Call 3]
LLM1 --> Out[Out]
LLM2 --> Out
LLM3 --> Out
style In fill:#8B0000,color:#fff
style Router fill:#2E8B57,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
#### Agentic Orchestrator Worker
Create AI agents that orchestrate and distribute tasks among specialized workers.
```mermaid
flowchart LR
In[In] --> Router[LLM Call Router]
Router --> LLM1[LLM Call 1]
Router --> LLM2[LLM Call 2]
Router --> LLM3[LLM Call 3]
LLM1 --> Synthesizer[Synthesizer]
LLM2 --> Synthesizer
LLM3 --> Synthesizer
Synthesizer --> Out[Out]
style In fill:#8B0000,color:#fff
style Router fill:#2E8B57,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Synthesizer fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
#### Agentic Autonomous Workflow
Create AI agents that can autonomously monitor, act, and adapt based on environment feedback.
```mermaid
flowchart LR
Human[Human] <--> LLM[LLM Call]
LLM -->|ACTION| Environment[Environment]
Environment -->|FEEDBACK| LLM
LLM --> Stop[Stop]
style Human fill:#8B0000,color:#fff
style LLM fill:#2E8B57,color:#fff
style Environment fill:#8B0000,color:#fff
style Stop fill:#333,color:#fff
```
#### Agentic Parallelization
Create AI agents that can execute tasks in parallel for improved performance.
```mermaid
flowchart LR
In[In] --> LLM2[LLM Call 2]
In --> LLM1[LLM Call 1]
In --> LLM3[LLM Call 3]
LLM1 --> Aggregator[Aggregator]
LLM2 --> Aggregator
LLM3 --> Aggregator
Aggregator --> Out[Out]
style In fill:#8B0000,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Aggregator fill:#fff,color:#000
style Out fill:#8B0000,color:#fff
```
#### Agentic Prompt Chaining
Create AI agents with sequential prompt chaining for complex workflows.
```mermaid
flowchart LR
In[In] --> LLM1[LLM Call 1] --> Gate{Gate}
Gate -->|Pass| LLM2[LLM Call 2] -->|Output 2| LLM3[LLM Call 3] --> Out[Out]
Gate -->|Fail| Exit[Exit]
style In fill:#8B0000,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
style Exit fill:#8B0000,color:#fff
```
#### Agentic Evaluator Optimizer
Create AI agents that can generate and optimize solutions through iterative feedback.
```mermaid
flowchart LR
In[In] --> Generator[LLM Call Generator]
Generator -->|SOLUTION| Evaluator[LLM Call Evaluator] -->|ACCEPTED| Out[Out]
Evaluator -->|REJECTED + FEEDBACK| Generator
style In fill:#8B0000,color:#fff
style Generator fill:#2E8B57,color:#fff
style Evaluator fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
#### Repetitive Agents
Create AI agents that can efficiently handle repetitive tasks through automated loops.
```mermaid
flowchart LR
In[Input] --> LoopAgent[("Looping Agent")]
LoopAgent --> Task[Task]
Task --> |Next iteration| LoopAgent
Task --> |Done| Out[Output]
style In fill:#8B0000,color:#fff
style LoopAgent fill:#2E8B57,color:#fff,shape:circle
style Task fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## Adding Models
<div align="center">
<a href="https://docs.praison.ai/models">
<p align="center">
<img src="https://img.shields.io/badge/%F0%9F%93%9A_Models-Visit_docs.praison.ai-blue?style=for-the-badge&logo=bookstack&logoColor=white" alt="Models" />
</p>
</a>
</div>
## Ollama Integration
```bash
export OPENAI_BASE_URL=http://localhost:11434/v1
```
## Groq Integration
Replace xxxx with Groq API KEY:
```bash
export OPENAI_API_KEY=xxxxxxxxxxx
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
```
## No Code Options
## Agents Playbook
### Simple Playbook Example
```yaml
framework: praisonai
topic: Artificial Intelligence
roles:
screenwriter:
backstory: "Skilled in crafting scripts with engaging dialogue about {topic}."
goal: Create scripts from concepts.
role: Screenwriter
tasks:
scriptwriting_task:
description: "Develop scripts with compelling characters and dialogue about {topic}."
expected_output: "Complete script ready for production."
```
*To run the playbook:*
```bash
praisonai agents.yaml
```
## Use 100+ Models
- https://docs.praison.ai/models/
<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>
## Development:
Below is used for development only.
### Using uv
```bash
# Install uv if you haven't already
pip install uv
# Install from requirements
uv pip install -r pyproject.toml
# Install with extras
uv pip install -r pyproject.toml --extra code
uv pip install -r pyproject.toml --extra "crewai,autogen"
```
## Contributing
- Fork on GitHub: Use the "Fork" button on the repository page.
- Clone your fork: `git clone https://github.com/yourusername/praisonAI.git`
- Create a branch: `git checkout -b new-feature`
- Make changes and commit: `git commit -am "Add some feature"`
- Push to your fork: `git push origin new-feature`
- Submit a pull request via GitHub's web interface.
- Await feedback from project maintainers.
## Other Features
- 🔄 Use CrewAI or AutoGen Framework
- 💻 Chat with ENTIRE Codebase
- 🎨 Interactive UIs
- 📄 YAML-based Configuration
- 🛠️ Custom Tool Integration
- 🔍 Internet Search Capability (using Crawl4AI and Tavily)
- 🖼️ Vision Language Model (VLM) Support
- 🎙️ Real-time Voice Interaction
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=MervinPraison/PraisonAI&type=Date)](https://docs.praison.ai)
## License
Praison AI is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
## Video Tutorials
| Topic | Video |
|-------|--------|
| Introduction | [![Introduction](https://img.youtube.com/vi/Fn1lQjC0GO0/0.jpg)](https://www.youtube.com/watch?v=Fn1lQjC0GO0) |
| Tools Overview | [![Tools Overview](https://img.youtube.com/vi/XaQRgRpV7jo/0.jpg)](https://www.youtube.com/watch?v=XaQRgRpV7jo) |
| Custom Tools | [![Custom Tools](https://img.youtube.com/vi/JSU2Rndh06c/0.jpg)](https://www.youtube.com/watch?v=JSU2Rndh06c) |
| Firecrawl Integration | [![Firecrawl](https://img.youtube.com/vi/UoqUDcLcOYo/0.jpg)](https://www.youtube.com/watch?v=UoqUDcLcOYo) |
| User Interface | [![UI](https://img.youtube.com/vi/tg-ZjNl3OCg/0.jpg)](https://www.youtube.com/watch?v=tg-ZjNl3OCg) |
| Crawl4AI Integration | [![Crawl4AI](https://img.youtube.com/vi/KAvuVUh0XU8/0.jpg)](https://www.youtube.com/watch?v=KAvuVUh0XU8) |
| Chat Interface | [![Chat](https://img.youtube.com/vi/sw3uDqn2h1Y/0.jpg)](https://www.youtube.com/watch?v=sw3uDqn2h1Y) |
| Code Interface | [![Code](https://img.youtube.com/vi/_5jQayO-MQY/0.jpg)](https://www.youtube.com/watch?v=_5jQayO-MQY) |
| Mem0 Integration | [![Mem0](https://img.youtube.com/vi/KIGSgRxf1cY/0.jpg)](https://www.youtube.com/watch?v=KIGSgRxf1cY) |
| Training | [![Training](https://img.youtube.com/vi/aLawE8kwCrI/0.jpg)](https://www.youtube.com/watch?v=aLawE8kwCrI) |
| Realtime Voice Interface | [![Realtime](https://img.youtube.com/vi/frRHfevTCSw/0.jpg)](https://www.youtube.com/watch?v=frRHfevTCSw) |
| Call Interface | [![Call](https://img.youtube.com/vi/m1cwrUG2iAk/0.jpg)](https://www.youtube.com/watch?v=m1cwrUG2iAk) |
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
-67
View File
@@ -1,67 +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
llm:
model: "groq/llama3-70b-8192"
function_calling_llm:
model: "google/gemini-1.5-flash-001"
allow_delegation: False
max_execution_time:
max_iter:
max_rpm:
verbose: True
cache: True
system_template:
prompt_template:
response_template:
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.
config:
max_iter: 5
output_file: "output/data_analysis.txt"
tools:
- 'InternetSearchTool'
medical_writer:
backstory: Skilled in translating complex medical information into accessible
content.
goal: Compile comprehensive content on lung disease causes
role: Medical Writer
llm:
model: "anthropic/claude-3-haiku-20240307"
function_calling_llm:
model: "openai/gpt-4o"
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.
async_execution: True
output_file: "output/medical_writer.txt"
create_directory:
context:
- data_analysis
tools:
- ''
editor:
backstory: Proficient in editing medical content for accuracy and clarity.
goal: Review and refine content on lung disease causes
role: Editor
llm:
model: "cohere/command-r"
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.
output_file: "output/editor.txt"
tools:
- ''
dependencies: []
-44
View File
@@ -1,44 +0,0 @@
framework: praisonai
process: sequential
topic: create movie script about cat in mars
memory: false
roles:
researcher:
backstory: Skilled in research, with a focus on gathering accurate and relevant
information.
goal: Gather information about Mars and cats
role: Researcher
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
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
tasks:
story_concept_development:
description: Use the research findings to craft a unique story concept for
a movie about a cat in Mars.
expected_output: Document with narrative arcs, character bios, and settings.
tools:
- ''
scriptwriter:
backstory: Expert in dialogue and script structure, translating concepts into
scripts.
goal: Write a movie script about a cat in Mars
role: Scriptwriter
tasks:
scriptwriting_task:
description: Turn the story concept into a production-ready movie script,
including dialogue and scene details.
expected_output: Final movie script with dialogue and scene details.
tools:
- ''
dependencies: []
-8
View File
@@ -1,8 +0,0 @@
1. Make minimal code changes as possible
2. if you are creating function, make sure to name it in more easy, user friendly , optimised manner.
3. Never copy the exact code if presented with a code from other location or file or codebase, just make it optimised
4. Always Follow the principle LESS IS MORE
5. Make it minimal change as possible
6. Firstly try not to make any modification to the existing code as possible
7. Only modify the existing code if its highly required, without that if it cant be done, then add new code section.
8. If you are adding new code, make sure to add it in a way that it can be easily integrated with the existing codebase.
-43
View File
@@ -1,43 +0,0 @@
FROM mcr.microsoft.com/devcontainers/python:3.11
# Prevent apt from showing prompts
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Create a non-root user
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Create the user and group only if they don't exist
RUN if ! getent group $USER_GID > /dev/null 2>&1; then \
groupadd --gid $USER_GID $USERNAME; \
fi && \
if ! getent passwd $USER_UID > /dev/null 2>&1; then \
useradd --uid $USER_UID --gid $USER_GID -m $USERNAME; \
fi && \
apt-get update && \
apt-get install -y sudo && \
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \
chmod 0440 /etc/sudoers.d/$USERNAME
# Set Python environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# Install Python dependencies
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp
# Switch to non-root user
USER $USERNAME
# Set the default shell to bash
ENV SHELL=/bin/bash
-36
View File
@@ -1,36 +0,0 @@
{
"name": "PraisonAI Development",
"dockerFile": "Dockerfile",
"context": "..",
"runArgs": [
"--env-file",
".env",
"--network=host"
],
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-toolsai.jupyter",
"yzhang.markdown-all-in-one",
"streetsidesoftware.code-spell-checker"
],
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"editor.rulers": [88],
"files.trimTrailingWhitespace": true
}
}
},
"remoteUser": "vscode",
"updateRemoteUserUID": false,
"forwardPorts": [],
"appPort": ["56040:56040"],
"overrideCommand": false,
"init": true
}
-87
View File
@@ -1,87 +0,0 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual Environment
venv/
env/
ENV/
.env
.venv
env.bak/
venv.bak/
# IDE
.idea/
.vscode/
*.swp
*.swo
.project
.pydevproject
.settings/
# Testing
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Documentation
docs/_build/
docs/generated/
# Jupyter Notebook
.ipynb_checkpoints
*.ipynb
# Logs and databases
*.log
*.sqlite
*.db
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
.test
praisonaiaagents.egg-info
praisonaiagents.egg-info
app.py
outputs
praisonaiagents/build
praisonaiagents/dist
praisonaiagents/praisonaiagents.egg-info
dist
build
*.mp4
*.png
graph.py
chroma_db/
View File
Whitespace-only changes.
-32
View File
@@ -1,32 +0,0 @@
.cursorrules
.gitignore
.praisoncontext
.praisonignore
.windsurfrules
async_example.py
async_example_full.py
async_example_full_multigroups.py
auto_agents_example.py
code_agents_example.py
example_callback.py
example_custom_tools.py
example_sequential.py
image.jpg
langchain_example.py
langchain_logs.py
long_term.db
mini_agents_example.py
multimodal.py
praisonaiagents/tools/*
praisonaiagents/process/*
pyproject.toml
short_term.db
structured_agents_example.py
structured_response_example.py
test.py
tools_example.py
uv.lock
workflow_example_basic.py
workflow_example_detailed.py
__pycache__
__pycache__/*
-8
View File
@@ -1,8 +0,0 @@
1. Make minimal code changes as possible
2. if you are creating function, make sure to name it in more easy, user friendly , optimised manner.
3. Never copy the exact code if presented with a code from other location or file or codebase, just make it optimised
4. Always Follow the principle LESS IS MORE
5. Make it minimal change as possible
6. Firstly try not to make any modification to the existing code as possible
7. Only modify the existing code if its highly required, without that if it cant be done, then add new code section.
8. If you are adding new code, make sure to add it in a way that it can be easily integrated with the existing codebase.
-45
View File
@@ -1,45 +0,0 @@
from praisonaiagents import Agent
# Detailed LLM configuration
llm_config = {
"model": "gemini/gemini-1.5-flash-latest", # Model name without provider prefix
# Core settings
"temperature": 0.7, # Controls randomness (like temperature)
"timeout": 30, # Timeout in seconds
"top_p": 0.9, # Nucleus sampling parameter
"max_tokens": 1000, # Max tokens in response
# Advanced parameters
"presence_penalty": 0.1, # Penalize repetition of topics (-2.0 to 2.0)
"frequency_penalty": 0.1, # Penalize token repetition (-2.0 to 2.0)
# API settings (optional)
"api_key": None, # Your API key (or use environment variable)
"base_url": None, # Custom API endpoint if needed
# Response formatting
"response_format": { # Force specific response format
"type": "text" # Options: "text", "json_object"
},
# Additional controls
"seed": 42, # For reproducible responses
"stop_phrases": ["##", "END"], # Custom stop sequences
}
agent = Agent(
instructions="You are a helpful Assistant specialized in scientific explanations. "
"Provide clear, accurate, and engaging responses.",
llm=llm_config, # Pass the detailed configuration
verbose=True, # Enable detailed output
markdown=True, # Format responses in markdown
self_reflect=True, # Enable self-reflection
max_reflect=3, # Maximum reflection iterations
min_reflect=1 # Minimum reflection iterations
)
# Test the agent
response = agent.start("Why is the sky blue? Please explain in simple terms.")
print(response)
-18
View File
@@ -1,18 +0,0 @@
import asyncio
from praisonaiagents import Agent
async def main():
agent = Agent(
instructions="You are a helpful assistant",
llm="gemini/gemini-1.5-flash-8b",
self_reflect=True,
verbose=True
)
# Use achat instead of start/chat for async operation
response = await agent.achat("Why sky is Blue in 1000 words?")
print(response)
if __name__ == "__main__":
# Run the async main function
asyncio.run(main())
-10
View File
@@ -1,10 +0,0 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gemini/gemini-1.5-flash-8b",
self_reflect=True,
verbose=True
)
agent.start("Why sky is Blue?")
-127
View File
@@ -1,127 +0,0 @@
import asyncio
import logging
from typing import List, Dict, Any
from pydantic import BaseModel
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from tavily import AsyncTavilyClient
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
llm_config = {
"model": "gemini/gemini-1.5-flash-8b",
"response_format": {
"type": "text"
}
}
# Define output model
class SearchResult(BaseModel):
query: str
results: List[Dict[str, Any]]
total_results: int
# Define Tavily search tool
async def tavily_search(query) -> Dict[str, Any]:
"""Async Tavily search tool that returns structured results"""
client = AsyncTavilyClient()
try:
results = await client.search(query)
print(f"Tavily search results: {results}")
return {
"query": query,
"results": results.get("results", []),
"total_results": len(results.get("results", []))
}
except Exception as e:
logging.error(f"Tavily search error: {e}")
return {
"query": query,
"results": [],
"total_results": 0
}
# Define async callback
async def async_callback(output: TaskOutput):
if output.output_format == "JSON":
logging.info(f"Search completed: {output.json_dict.get('query', '')}")
elif output.output_format == "Pydantic":
logging.info(f"Search completed: {output.pydantic}")
async def run_parallel_searches():
# Create search agent with direct tool function
search_agent = Agent(
name="TavilySearchAgent",
role="Search Specialist",
goal="Perform parallel web searches with high accuracy",
backstory="Expert in web search and information retrieval",
tools=[tavily_search],
llm=llm_config
)
# Create summary agent
summary_agent = Agent(
name="ContentSynthesizer",
role="Research Analyst",
goal="Synthesize search results into coherent insights",
backstory="Expert in analyzing and combining multiple sources of information",
llm=llm_config
)
# Define search topics
search_topics = [
"Latest AI breakthroughs 2024",
"Future of quantum computing",
"Advancements in robotics"
]
# Create parallel search tasks
search_tasks = [
Task(
name=f"search_{i}",
description=f"Search and analyze: {topic}",
expected_output="Comprehensive search results with analysis",
agent=search_agent,
async_execution=True,
callback=async_callback,
) for i, topic in enumerate(search_topics)
]
# Create summary task
summary_task = Task(
name="synthesize_results",
description="Create a comprehensive summary of all search findings",
expected_output="Synthesized insights from all searches",
agent=summary_agent,
async_execution=False,
context=search_tasks
)
# Initialize agents manager
agents = PraisonAIAgents(
agents=[search_agent, summary_agent],
tasks=search_tasks + [summary_task]
)
# Execute tasks
results = await agents.astart()
return {
"search_results": [str(results["task_results"][i]) for i in range(len(search_tasks))],
"summary": str(results["task_results"][summary_task.id]),
"topics": search_topics
}
async def main():
try:
logging.info("Starting parallel Tavily searches...")
results = await run_parallel_searches()
logging.info("Search process completed successfully")
print("\nResults Summary:")
for topic, result in zip(results["topics"], results["search_results"]):
print(f"\n{topic}:\n{result}")
print(f"\nFinal Summary:\n{results['summary']}")
except Exception as e:
logging.error(f"Error in execution: {e}")
if __name__ == "__main__":
asyncio.run(main())
-119
View File
@@ -1,119 +0,0 @@
import asyncio
import logging
from typing import List, Dict, Any
from pydantic import BaseModel
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from tavily import AsyncTavilyClient
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Define output model
class SearchResult(BaseModel):
query: str
results: List[Dict[str, Any]]
total_results: int
# Define Tavily search tool
async def tavily_search(query: str) -> Dict[str, Any]:
"""Async Tavily search tool that returns structured results"""
client = AsyncTavilyClient()
try:
results = await client.search(query)
print(f"Tavily search results: {results}")
return {
"query": query,
"results": results.get("results", []),
"total_results": len(results.get("results", []))
}
except Exception as e:
logging.error(f"Tavily search error: {e}")
return {
"query": query,
"results": [],
"total_results": 0
}
# Define async callback
async def async_callback(output: TaskOutput):
if output.output_format == "JSON":
logging.info(f"Search completed: {output.json_dict.get('query', '')}")
elif output.output_format == "Pydantic":
logging.info(f"Search completed: {output.pydantic}")
async def run_parallel_searches():
# Create search agent with direct tool function
search_agent = Agent(
name="TavilySearchAgent",
role="Search Specialist",
goal="Perform parallel web searches with high accuracy",
backstory="Expert in web search and information retrieval",
tools=[tavily_search]
)
# Create summary agent
summary_agent = Agent(
name="ContentSynthesizer",
role="Research Analyst",
goal="Synthesize search results into coherent insights",
backstory="Expert in analyzing and combining multiple sources of information"
)
# Define search topics
search_topics = [
"Latest AI breakthroughs 2024",
"Future of quantum computing",
"Advancements in robotics"
]
# Create parallel search tasks
search_tasks = [
Task(
name=f"search_{i}",
description=f"Search and analyze: {topic}",
expected_output="Comprehensive search results with analysis",
agent=search_agent,
async_execution=True,
callback=async_callback,
output_json=SearchResult
) for i, topic in enumerate(search_topics)
]
# Create summary task
summary_task = Task(
name="synthesize_results",
description="Create a comprehensive summary of all search findings",
expected_output="Synthesized insights from all searches",
agent=summary_agent,
async_execution=False,
context=search_tasks
)
# Initialize agents manager
agents = PraisonAIAgents(
agents=[search_agent, summary_agent],
tasks=search_tasks + [summary_task]
)
# Execute tasks
results = await agents.astart()
return {
"search_results": [str(results["task_results"][i]) for i in range(len(search_tasks))],
"summary": str(results["task_results"][summary_task.id]),
"topics": search_topics
}
async def main():
try:
logging.info("Starting parallel Tavily searches...")
results = await run_parallel_searches()
logging.info("Search process completed successfully")
print("\nResults Summary:")
for topic, result in zip(results["topics"], results["search_results"]):
print(f"\n{topic}:\n{result}")
print(f"\nFinal Summary:\n{results['summary']}")
except Exception as e:
logging.error(f"Error in execution: {e}")
if __name__ == "__main__":
asyncio.run(main())
-254
View File
@@ -1,254 +0,0 @@
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
import logging
# Configure logging with more detail
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(name)s:%(lineno)d - %(message)s'
)
logger = logging.getLogger(__name__)
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) -> Dict:
"""
Asynchronous search using DuckDuckGo.
Args:
query (str): The search query.
Returns:
list: Search results
"""
logger.debug(f"Starting async_search_tool with query: {query}")
display_tool_call(f"Running async search for: {query}", console)
await asyncio.sleep(1) # Simulate network delay
try:
results = []
ddgs = DDGS()
logger.debug("Performing DuckDuckGo search")
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
logger.debug(f"Search completed, found {len(results)} results")
return {
"query": query,
"results": results,
"total_results": len(results)
}
except Exception as e:
error_msg = f"Error during async search: {e}"
logger.error(f"Error in async_search_tool: {e}", exc_info=True)
display_error(error_msg, console)
error_logs.append(error_msg)
return {
"query": query,
"results": [],
"total_results": 0
}
# 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())
-159
View File
@@ -1,159 +0,0 @@
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
import logging
# Configure logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# 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())
-248
View File
@@ -1,248 +0,0 @@
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())
-11
View File
@@ -1,11 +0,0 @@
from praisonaiagents import AutoAgents
from praisonaiagents.tools import duckduckgo
agents = AutoAgents(
instructions="Search for information about AI Agents",
tools=[duckduckgo],
process="sequential",
verbose=True
)
agents.start()
-114
View File
@@ -1,114 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
def get_environment_state():
"""Simulates getting current environment state"""
current_time = int(time.time())
states = ["normal", "critical", "optimal"]
state = states[current_time % 3]
print(f"Environment state: {state}")
return state
def perform_action(state: str):
"""Simulates performing an action based on state"""
actions = {
"normal": "maintain",
"critical": "fix",
"optimal": "enhance"
}
action = actions.get(state, "observe")
print(f"Performing action: {action} for state: {state}")
return action
def get_feedback():
"""Simulates environment feedback"""
current_time = int(time.time())
feedback = "positive" if current_time % 2 == 0 else "negative"
print(f"Feedback received: {feedback}")
return feedback
# Create specialized agents
llm_caller = Agent(
name="Environment Monitor",
role="State analyzer",
goal="Monitor environment and analyze state",
instructions="Check environment state and provide analysis",
tools=[get_environment_state]
)
action_agent = Agent(
name="Action Executor",
role="Action performer",
goal="Execute appropriate actions based on state",
instructions="Determine and perform actions based on environment state",
tools=[perform_action]
)
feedback_agent = Agent(
name="Feedback Processor",
role="Feedback analyzer",
goal="Process environment feedback and adapt strategy",
instructions="Analyze feedback and provide adaptation recommendations",
tools=[get_feedback]
)
# Create tasks for autonomous workflow
monitor_task = Task(
name="monitor_environment",
description="Monitor and analyze environment state",
expected_output="Current environment state analysis",
agent=llm_caller,
is_start=True,
task_type="decision",
next_tasks=["execute_action"],
condition={
"normal": ["execute_action"],
"critical": ["execute_action"],
"optimal": "exit"
}
)
action_task = Task(
name="execute_action",
description="Execute appropriate action based on state",
expected_output="Action execution result",
agent=action_agent,
next_tasks=["process_feedback"]
)
feedback_task = Task(
name="process_feedback",
description="Process feedback and adapt strategy",
expected_output="Strategy adaptation based on feedback",
agent=feedback_agent,
next_tasks=["monitor_environment"], # Create feedback loop
context=[monitor_task, action_task] # Access to previous states and actions
)
# Create workflow manager
workflow = PraisonAIAgents(
agents=[llm_caller, action_agent, feedback_agent],
tasks=[monitor_task, action_task, feedback_task],
process="workflow",
verbose=True
)
def main():
print("\nStarting Autonomous Agent Workflow...")
print("=" * 50)
# Run autonomous workflow
results = workflow.start()
# Print results
print("\nAutonomous Agent Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
task_name = result.description
print(f"\nTask: {task_name}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
main()
-8
View File
@@ -1,8 +0,0 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-4o-mini"
)
agent.start("Why sky is Blue?")
-14
View File
@@ -1,14 +0,0 @@
from praisonaiagents.knowledge import Chunking
# No heavy imports or initialization happens here
chunking = Chunking(chunker_type='token')
# Chunker is only initialized when first used
chunks = chunking.chunk("Your text here")
# Embedding model is only loaded if using semantic chunking
semantic_chunking = Chunking(chunker_type='recursive')
# Embedding model and chunker are loaded here on first use
semantic_chunks = semantic_chunking.chunk("Your text here")
print(semantic_chunks)
-97
View File
@@ -1,97 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
from gitingest import ingest
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
return agents.start(context_text)
if __name__ == "__main__":
# Example usage
code_source = "https://github.com/openai/openai-python/tree/main/src/openai/cli/_api/chat" # GitHub URL or local directory
result = analyze_code(code_source)
print(result)
-217
View File
@@ -1,217 +0,0 @@
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict, Any
from gitingest import ingest
# Import the same classes and code from code-analysis-agents.py
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Create code analyzer agent
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
# Create analysis task
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
result = agents.start(context_text)
# Extract the Pydantic model from the result
if isinstance(result, dict) and 'task_results' in result:
# Get the first task result's pydantic output
analysis_result = result['task_results'][0].pydantic
if isinstance(analysis_result, CodeAnalysisReport):
return analysis_result
# If we can't get the Pydantic model, create one from the raw data
return CodeAnalysisReport(**result)
def display_code_metrics(metrics, cols):
"""Display code metrics in columns with color-coded scores"""
for i, metric in enumerate(metrics):
score = metric.score
color = "red" if score < 60 else "orange" if score < 75 else "green"
# Use modulo to alternate between columns
with cols[i % len(cols)]:
st.markdown(f"### {metric.category}")
st.markdown(f"**Score:** :{color}[{score}%]")
for finding in metric.findings:
st.markdown(f"• {finding}")
def display_section(title: str, items: list, icon: str = "•"):
"""Display a section with items in a consistent format"""
st.markdown(f"### {title}")
for item in items:
if isinstance(item, dict):
for key, value in item.items():
st.markdown(f"{icon} **{key}**: {value}")
else:
st.markdown(f"{icon} {item}")
def main():
st.set_page_config(
page_title="Code Analysis Agent",
layout="wide",
initial_sidebar_state="expanded"
)
st.title("Code Analysis Agent")
with st.sidebar:
st.header("Input")
code_source = st.text_input(
"GitHub URL or Local Path",
placeholder="https://github.com/username/repo or /path/to/directory"
)
analyze_button = st.button("Analyze Code", type="primary")
if analyze_button and code_source:
try:
with st.spinner("Analyzing code..."):
result = analyze_code(code_source)
# Overall Metrics
st.header("Overall Metrics")
cols = st.columns(6)
metrics = {
"Overall Quality": result.overall_quality,
"Architecture": result.architecture_score,
"Maintainability": result.maintainability_score,
"Performance": result.performance_score,
"Security": result.security_score,
"Test Coverage": result.test_coverage
}
for (metric, value), col in zip(metrics.items(), cols):
color = "red" if value < 60 else "orange" if value < 75 else "green"
col.metric(metric, f"{value}%")
col.markdown(f":{color}[{'●' * (value // 20)}]")
# Detailed Analysis
st.header("Detailed Analysis")
metric_cols = st.columns(2)
display_code_metrics(result.code_metrics, metric_cols)
# Technology Stack
col1, col2 = st.columns(2)
with col1:
st.header("Technology Stack")
for tech in result.tech_stack:
st.markdown(f"🔧 {tech}")
with col2:
st.header("Complexity Metrics")
for metric, value in result.complexity_metrics.items():
st.metric(metric.replace('_', ' ').title(), value)
# Key Findings
st.header("Key Findings")
cols = st.columns(2)
with cols[0]:
display_section("✅ Strengths", result.key_strengths)
display_section("🔄 Best Practices", result.best_practices)
with cols[1]:
display_section("⚠️ Areas for Improvement", result.improvement_areas)
display_section("❗ Potential Risks", result.potential_risks)
# Recommendations
st.header("Recommendations")
for i, rec in enumerate(result.recommendations, 1):
st.markdown(f"**{i}.** {rec}")
# Documentation Quality
st.header("Documentation")
doc_score = result.documentation_quality
color = "red" if doc_score < 60 else "orange" if doc_score < 75 else "green"
st.markdown(f"Documentation Quality: :{color}[{doc_score}%]")
except Exception as e:
st.error(f"Error analyzing code: {str(e)}")
st.exception(e)
elif analyze_button:
st.warning("Please enter a GitHub URL or local path")
if __name__ == "__main__":
main()
-50
View File
@@ -1,50 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import json
from e2b_code_interpreter import Sandbox
def code_interpreter(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})
code_agent = Agent(
name="code_agent",
llm="gpt-4o-mini",
backstory="Expert in writing Python scripts",
self_reflect=False
)
execution_agent = Agent(
name="execution_agent",
llm="gpt-4o-mini",
backstory="Expert in executing Python scripts",
self_reflect=False,
tools=[code_interpreter]
)
code_agent_task = Task(
description="Write a simple Python script to print 'Hello, World!'",
expected_output="A Python script that prints 'Hello, World!'",
agent=code_agent
)
execution_agent_task = Task(
description="Execute the Python script",
expected_output="The output of the Python script",
agent=execution_agent
)
agents = PraisonAIAgents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task])
agents.start()
-108
View File
@@ -1,108 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import List, Dict
def analyze_code_changes():
"""Simulates code analysis"""
issues = [
{"type": "style", "severity": "low", "file": "main.py"},
{"type": "security", "severity": "high", "file": "auth.py"},
{"type": "performance", "severity": "medium", "file": "data.py"}
]
return issues[int(time.time()) % 3]
def suggest_fixes(issue: Dict):
"""Simulates fix suggestions"""
fixes = {
"style": "Apply PEP 8 formatting",
"security": "Implement input validation",
"performance": "Use list comprehension"
}
return fixes.get(issue["type"], "Review manually")
def apply_automated_fix(fix: str):
"""Simulates applying automated fixes"""
success = int(time.time()) % 2 == 0
return "fixed" if success else "manual_review"
# Create specialized agents
analyzer = Agent(
name="Code Analyzer",
role="Code analysis",
goal="Analyze code changes and identify issues",
instructions="Review code changes and report issues",
tools=[analyze_code_changes]
)
fix_suggester = Agent(
name="Fix Suggester",
role="Solution provider",
goal="Suggest fixes for identified issues",
instructions="Provide appropriate fix suggestions",
tools=[suggest_fixes]
)
fix_applier = Agent(
name="Fix Applier",
role="Fix implementation",
goal="Apply suggested fixes automatically when possible",
instructions="Implement suggested fixes and report results",
tools=[apply_automated_fix]
)
# Create workflow tasks
analysis_task = Task(
name="analyze_code",
description="Analyze code changes for issues",
expected_output="Identified code issues",
agent=analyzer,
is_start=True,
next_tasks=["suggest_fixes"]
)
suggestion_task = Task(
name="suggest_fixes",
description="Suggest fixes for identified issues",
expected_output="Fix suggestions",
agent=fix_suggester,
next_tasks=["apply_fixes"]
)
fix_task = Task(
name="apply_fixes",
description="Apply suggested fixes",
expected_output="Fix application status",
agent=fix_applier,
task_type="decision",
condition={
"fixed": "",
"manual_review": ["suggest_fixes"] # Loop back for manual review
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[analyzer, fix_suggester, fix_applier],
tasks=[analysis_task, suggestion_task, fix_task],
process="workflow",
verbose=True
)
def main():
print("\nStarting Code Review Workflow...")
print("=" * 50)
# Run workflow
results = workflow.start()
# Print results
print("\nCode Review Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
main()
-98
View File
@@ -1,98 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
class SkillMetrics(BaseModel):
name: str
score: int
comments: str
class CVAnalysisReport(BaseModel):
overall_score: int
skill_metrics: List[SkillMetrics]
experience_score: int
education_score: int
presentation_score: int
achievement_impact_score: int
market_readiness: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[Dict[str, int]]
soft_skills: List[Dict[str, int]]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
# Create single CV analysis agent
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
# Single comprehensive analysis task
cv_analysis_task = Task(
description="""Perform a detailed CV analysis with scoring metrics and provide output in the following format:
1. Overall Score (0-100):
- Calculate based on weighted average of all metrics
2. Individual Skill Metrics:
- For each major skill found in CV:
* Name of skill
* Score (0-100)
* Specific feedback/comments
3. Core Metrics (0-100 each):
- Experience Score: Based on relevance and years
- Education Score: Based on relevance and level
- Presentation Score: CV format, clarity, structure
- Achievement Impact Score: Measurable results
- Market Readiness: Current market fit
4. Technical Skills:
- List each skill with proficiency score (0-100)
- Example: {"Python": 85, "AWS": 70}
5. Soft Skills:
- List each skill with proficiency score (0-100)
- Example: {"Communication": 90, "Leadership": 75}
6. Detailed Analysis:
- Key Strengths: Top 3-5 standout points
- Areas for Improvement: 3-5 specific points
- Market Fit: Current industry alignment
- Skill Gaps: Missing critical skills for target role
- Key Achievements: Quantifiable accomplishments
- Impact Metrics: {"metric": "value"}
- Areas of Expertise: Primary domains of expertise
7. Recommendations:
- 3-5 actionable steps for improvement
Provide clear justification for all scores and ensure feedback is specific and actionable.""",
expected_output="Structured CV analysis report with detailed metrics and scoring justification",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport
)
# Create and run the agent
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_analysis_task]
)
# Read and pass CV content through start()
with open('cv.txt', 'r') as file:
cv_content = file.read()
# Start the analysis by passing CV content
result = agents.start(cv_content)
print(result)
-202
View File
@@ -1,202 +0,0 @@
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import json
import asyncio
import nest_asyncio
from functools import partial
# Enable nested event loops
nest_asyncio.apply()
class SkillMetrics(BaseModel):
name: str
score: int
comments: str
class CVAnalysisReport(BaseModel):
overall_score: int
skill_metrics: List[SkillMetrics]
experience_score: int
education_score: int
presentation_score: int
achievement_impact_score: int
market_readiness: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[Dict[str, int]]
soft_skills: List[Dict[str, int]]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
async def analyze_cv_async(cv_content):
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
cv_analysis_task = Task(
description="""Perform a detailed CV analysis with scoring metrics and provide output in the following format:
1. Overall Score (0-100):
- Calculate based on weighted average of all metrics
2. Individual Skill Metrics:
- For each major skill found in CV:
* Name of skill
* Score (0-100)
* Specific feedback/comments
3. Core Metrics (0-100 each):
- Experience Score: Based on relevance and years
- Education Score: Based on relevance and level
- Presentation Score: CV format, clarity, structure
- Achievement Impact Score: Measurable results
- Market Readiness: Current market fit
4. Technical Skills:
- List each skill with proficiency score (0-100)
5. Soft Skills:
- List each skill with proficiency score (0-100)
6. Detailed Analysis sections
7. Recommendations:
- 3-5 actionable steps for improvement""",
expected_output="Structured CV analysis report with detailed metrics and scoring justification",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport
)
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_analysis_task]
)
try:
result = await agents.astart(cv_content)
return result['task_results'][0].pydantic
except Exception as e:
print(f"Error during analysis: {str(e)}")
raise e
def analyze_cv(cv_content):
async def run_analysis():
return await analyze_cv_async(cv_content)
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(run_analysis())
return result
except Exception as e:
raise e
finally:
loop.close()
def main():
st.set_page_config(page_title="CV Analyzer", layout="wide")
st.title("Professional CV Analyzer")
# File upload
cv_file = st.file_uploader("Upload your CV (TXT format)", type=['txt'])
if cv_file:
cv_content = cv_file.read().decode()
with st.spinner('Analyzing your CV...'):
try:
analysis = analyze_cv(cv_content)
# Display Overall Score
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Overall Score", f"{analysis.overall_score}/100")
with col2:
st.metric("Market Readiness", f"{analysis.market_readiness}/100")
with col3:
st.metric("Experience Score", f"{analysis.experience_score}/100")
# Core Metrics
st.subheader("Core Metrics")
metrics_cols = st.columns(4)
with metrics_cols[0]:
st.metric("Education", f"{analysis.education_score}/100")
with metrics_cols[1]:
st.metric("Presentation", f"{analysis.presentation_score}/100")
with metrics_cols[2]:
st.metric("Achievement Impact", f"{analysis.achievement_impact_score}/100")
with metrics_cols[3]:
st.metric("Market Readiness", f"{analysis.market_readiness}/100")
# Skill Metrics
st.subheader("Detailed Skill Analysis")
for skill in analysis.skill_metrics:
with st.expander(f"{skill.name} - Score: {skill.score}/100"):
st.write(skill.comments)
# Technical and Soft Skills
col1, col2 = st.columns(2)
with col1:
st.subheader("Technical Skills")
for skill in analysis.technical_skills:
for skill_name, score in skill.items():
st.progress(score/100)
st.caption(f"{skill_name}: {score}/100")
with col2:
st.subheader("Soft Skills")
for skill in analysis.soft_skills:
for skill_name, score in skill.items():
st.progress(score/100)
st.caption(f"{skill_name}: {score}/100")
# Key Information
st.subheader("Key Analysis")
col1, col2 = st.columns(2)
with col1:
st.write("🎯 Key Strengths")
for strength in analysis.key_strengths:
st.write(f"• {strength}")
st.write("🎮 Areas of Expertise")
for expertise in analysis.areas_of_expertise:
st.write(f"• {expertise}")
with col2:
st.write("🔄 Areas for Improvement")
for area in analysis.areas_for_improvement:
st.write(f"• {area}")
st.write("⚠️ Skill Gaps")
for gap in analysis.skill_gaps:
st.write(f"• {gap}")
# Impact Metrics
st.subheader("Impact Metrics")
for metric in analysis.impact_metrics:
for key, value in metric.items():
st.metric(key, value)
# Recommendations
st.subheader("📋 Recommendations")
for rec in analysis.recommendations:
st.write(f"• {rec}")
except Exception as e:
st.error(f"An error occurred during analysis: {str(e)}")
else:
st.info("Please upload your CV in TXT format to begin the analysis")
if __name__ == "__main__":
main()
-61
View File
@@ -1,61 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
class CVAnalysisReport(BaseModel):
overall_score: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[str]
soft_skills: List[str]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
# Create single CV analysis agent
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
# Read CV content first
with open('cv.txt', 'r') as file:
cv_content = file.read()
cv_key_strengths = Task(
description="List the key strengths to look",
expected_output="List of key strengths",
agent=cv_analyzer,
)
# Single comprehensive analysis task with CV content in context
cv_analysis_task = Task(
description="""Analyze the CV comprehensively including:
1. Technical and soft skills assessment
2. Experience and achievements evaluation
3. Overall CV evaluation with recommendations
Provide detailed insights and actionable recommendations.""",
expected_output="Complete CV analysis report",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport,
context=[cv_content, cv_key_strengths] # Pass CV content directly in task context
)
# Create and run the agent
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_key_strengths,cv_analysis_task],
process="sequential"
)
# Start the analysis - no need to pass content again since it's in task context
result = agents.start()
print(result)
-27
View File
@@ -1,27 +0,0 @@
# example 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
from praisonaiagents import Agent
from praisonaiagents import PraisonAIAgents
agent = Agent(
name="Internet Search Agent",
tools=[InternetSearchTool],
instructions="""
You are an agent that can search the internet for relevant information based on a query or latest news.
"""
)
# Run the agent
result = PraisonAIAgents(agents=[agent], verbose=10).start()
print(result)
-57
View File
@@ -1,57 +0,0 @@
Name: Alex Johnson
Location: London, UK
Professional Summary
Dynamic and results-oriented leader with a proven track record of driving innovation, scaling operations, and achieving transformational growth. Over 15 years of experience in engineering, strategic management, and executive leadership in the automotive and renewable energy sectors. Passionate about sustainable technologies and visionary leadership.
Professional Experience
Chief Operating Officer (COO)
NextGen Mobility Ltd. | Palo Alto, CA | 2020 – Present
Spearheaded global operations for an electric vehicle company, scaling production by 200% in three years.
Introduced automation-driven supply chain strategies, reducing costs by 15%.
Collaborated with R&D to launch three new EV models, driving 25% revenue growth annually.
Vice President of Engineering
ElectroDrive Systems | San Francisco, CA | 2015 – 2020
Led a team of 500+ engineers in developing next-generation EV batteries, achieving a 30% increase in energy efficiency.
Secured $50M in government funding for sustainable energy innovation.
Drove cross-functional collaboration, aligning product development with market needs.
Director of Renewable Energy Initiatives
GreenTech Innovations | London, UK | 2011 – 2015
Oversaw £100M projects in solar and wind energy deployment across Europe.
Established partnerships with policymakers to influence renewable energy legislation.
Pioneered a smart energy grid system, enhancing energy distribution efficiency by 40%.
Senior Project Manager
Innovate Auto Ltd. | Munich, Germany | 2008 – 2011
Managed R&D projects for autonomous driving technologies.
Delivered projects 20% under budget through strategic resource allocation.
Filed 10+ patents in automotive AI and renewable integration.
Mechanical Engineer
AutoFusion Technologies | Berlin, Germany | 2005 – 2008
Designed core systems for EV powertrains, optimising energy consumption by 15%.
Collaborated with suppliers to improve material efficiency, cutting costs by £5M annually.
Education
MBA in Strategic Management
Harvard Business School | Cambridge, MA | 2015
MSc in Renewable Energy Engineering
Imperial College London | London, UK | 2007
BSc in Mechanical Engineering
Technical University of Munich | Munich, Germany | 2005
Skills
Strategic Leadership & Visionary Thinking
Electric Vehicle Engineering
Renewable Energy Systems
Global Operations Management
Policy Advocacy & Government Relations
Supply Chain Optimisation
Achievements
Featured in Forbes 30 Under 40 for innovations in EV technology.
Author of The Future of Sustainable Mobility.
Keynote speaker at World Energy Summit, 2023.
-10
View File
@@ -1,10 +0,0 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import read_csv, read_excel, write_csv, write_excel, filter_data, get_summary, group_by, pivot_table
import os
agent = Agent(instructions="You are a Data Analyst Agent", tools=[read_csv, read_excel, write_csv, write_excel, filter_data, get_summary, group_by, pivot_table])
agent.start(f"""
Read the data from the csv file {os.path.join(os.path.dirname(__file__), "tesla-stock-price.csv")}
Analyse the data and give me the insights
read_csv to read the file
""")
-9
View File
@@ -1,9 +0,0 @@
# pip install praisonaiagents
# export OPENAI_BASE_URL=http://localhost:11434/v1
# ollama pull deepseek-r1
from praisonaiagents import Agent
agent = Agent(instructions="You are helpful Assisant", llm="deepseek-r1")
agent.start("Why sky is Blue?")
-62
View File
@@ -1,62 +0,0 @@
import streamlit as st
from praisonaiagents import Agent
def init_agent():
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
"embedding_dims": 1536
},
},
}
return Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["kag-research-paper.pdf"],
knowledge_config=config,
user_id="user1",
llm="deepseek-r1"
)
st.title("Knowledge Agent Chat")
if "agent" not in st.session_state:
st.session_state.agent = init_agent()
st.session_state.messages = []
if "messages" in st.session_state:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
prompt = st.chat_input("Ask a question...")
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
response = st.session_state.agent.start(prompt)
st.markdown(response)
st.session_state.messages.append({"role": "assistant", "content": response})
-54
View File
@@ -1,54 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
},
},
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="deepseek-r1"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
-62
View File
@@ -1,62 +0,0 @@
import streamlit as st
from praisonaiagents import Agent
def init_agent():
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
"embedding_dims": 1536
},
},
}
return Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["kag-research-paper.pdf"],
knowledge_config=config,
user_id="user1",
llm="deepseek-r1"
)
st.title("Knowledge Agent Chat")
if "agent" not in st.session_state:
st.session_state.agent = init_agent()
st.session_state.messages = []
if "messages" in st.session_state:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
prompt = st.chat_input("Ask a question...")
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
response = st.session_state.agent.start(prompt)
st.markdown(response)
st.session_state.messages.append({"role": "assistant", "content": response})
-39
View File
@@ -1,39 +0,0 @@
from praisonaiagents import Agent
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
"embedding_dims": 1536
},
},
}
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["kag-research-paper.pdf"], # Indexing
knowledge_config=config,
user_id="user1",
llm="deepseek-r1"
)
agent.start("What is KAG in one line?") # Retrieval
-3
View File
@@ -1,3 +0,0 @@
I am Mervin Praison, a software engineer and entrepreneur.
I am the founder of Praison AI, a company that is building AI agents to help people with their daily tasks.
-70
View File
@@ -1,70 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create generator and evaluator agents
generator = Agent(
name="Generator",
role="Solution generator",
goal="Generate initial solutions and incorporate feedback",
instructions=(
"1. Look at the context from previous tasks.\n"
"2. If you see that you have already produced 2 points, then add another 2 new points "
" so that the total becomes 10.\n"
"3. Otherwise, just produce the first 2 points.\n"
"4. Return only the final list of points, with no extra explanation."
)
)
evaluator = Agent(
name="Evaluator",
role="Solution evaluator",
goal="Evaluate solutions and provide improvement feedback",
instructions=(
"1. Count how many lines in the response start with a number and a period (like '1. ' or '2. ').\n"
"2. If there are 10 or more, respond with 'done'.\n"
"3. Otherwise, respond with 'more'.\n"
"4. Return only the single word: 'done' or 'more'."
)
)
# Create tasks for the feedback loop
generate_task = Task(
name="generate",
description="Write 2 points about AI incuding if anything exiting from previous points",
expected_output="2 points",
agent=generator,
is_start=True,
task_type="decision",
next_tasks=["evaluate"]
)
evaluate_task = Task(
name="evaluate",
description="Check if there are 10 points about AI",
expected_output="more or done",
agent=evaluator,
next_tasks=["generate"],
context=[generate_task],
task_type="decision",
condition={
"more": ["generate"], # Continue to generate
"done": [""] # Exit when optimization complete
}
)
# Create workflow manager
workflow = PraisonAIAgents(
agents=[generator, evaluator],
tasks=[generate_task, evaluate_task],
process="workflow",
verbose=True
)
# Run optimization workflow
results = workflow.start()
# Print results
print("\nEvaluator-Optimizer Results:")
for task_id, result in results["task_results"].items():
if result:
print(f"Task {task_id}: {result.raw}")
-204
View File
@@ -1,204 +0,0 @@
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()
-151
View File
@@ -1,151 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from typing import List, Dict, Union
from duckduckgo_search import DDGS
from langchain_community.tools import YouTubeSearchTool
from langchain_community.utilities import WikipediaAPIWrapper
# 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 []
def youtube_search_tool(query: str, inspect: bool = False, max_results: int = 2):
"""
Provide a custom wrapper around the YouTubeSearchTool.
Args:
query (str): The search query for YouTube.
inspect (bool): If True, returns tool inspection info instead of search results.
max_results (int): Maximum number of results to return (default: 2).
Returns:
Union[List[str], dict]: List of YouTube video URLs or tool inspection info.
"""
yt = YouTubeSearchTool()
if inspect:
inspection_info = {
"type": type(yt),
"attributes": [attr for attr in dir(yt) if not attr.startswith('_')],
"methods": {
"run": getattr(yt, 'run', None),
"arun": getattr(yt, 'arun', None)
},
"properties": {
"name": getattr(yt, 'name', 'youtube_search'),
"description": getattr(yt, 'description', 'Search YouTube videos'),
"return_direct": getattr(yt, 'return_direct', False)
}
}
return inspection_info
# Format query with max_results
formatted_query = f"{query}, {max_results}"
return yt.run(formatted_query)
def wikipedia_search_tool(query: str, inspect: bool = False, max_chars: int = 4000, top_k: int = 3):
"""
Provide a custom wrapper around langchain_community's WikipediaAPIWrapper.
Args:
query (str): A search query for Wikipedia.
inspect (bool): If True, returns tool inspection info instead of search results.
max_chars (int): Maximum characters to return (default: 4000).
top_k (int): Number of top results to consider (default: 3).
Returns:
Union[str, dict]: Summary from Wikipedia or tool inspection info if inspect=True.
"""
w = WikipediaAPIWrapper(
top_k_results=top_k,
doc_content_chars_max=max_chars,
lang='en'
)
if inspect:
inspection_info = {
"type": type(w),
"attributes": [attr for attr in dir(w) if not attr.startswith('_')],
"methods": {
"run": getattr(w, 'run', None),
"arun": getattr(w, 'arun', None)
},
"properties": {
"name": "wikipedia",
"description": "Search and get summaries from Wikipedia",
"top_k": w.top_k_results,
"lang": w.lang,
"max_chars": w.doc_content_chars_max
}
}
return inspection_info
try:
result = w.run(query)
return result
except Exception as e:
return f"Error searching Wikipedia: {str(e)}"
# 2. Agent
data_agent = Agent(
name="DataCollector",
role="Search Specialist",
goal="Perform internet searches to collect relevant information.",
backstory="Expert in finding and organizing internet data from multiple sources.",
tools=[internet_search_tool, youtube_search_tool, wikipedia_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()
-141
View File
@@ -1,141 +0,0 @@
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")
-5
View File
@@ -1,5 +0,0 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import get_stock_price, get_stock_info, get_historical_data
agent = Agent(instructions="You are a Research Agent", tools=[get_stock_price, get_stock_info, get_historical_data])
agent.start("Understand current stock price and historical data of Apple and Google. Tell me if I can invest in them")
-34
View File
@@ -1,34 +0,0 @@
import gradio as gr
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
def research(query):
agent = Agent(instructions="You are a Research Agent", tools=[duckduckgo])
result = agent.start(query)
# Format the result with enhanced markdown
formatted_result = f"""
{result}
----
*Generated by PraisonAI Research Assistant*
"""
return formatted_result
# Create a simple Gradio interface
demo = gr.Interface(
fn=research,
inputs=gr.Textbox(
label="Research Query",
placeholder="Enter your research topic...",
lines=2
),
outputs=gr.Markdown(
show_copy_button=True,
height=500,
container=True
),
title="AI Research Assistant",
description="Enter your research query below to get started!",
)
if __name__ == "__main__":
demo.launch()
View File
Whitespace-only changes.
-159
View File
@@ -1,159 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
-159
View File
@@ -1,159 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
-210
View File
@@ -1,210 +0,0 @@
import streamlit as st
import os
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import tempfile
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Set page config
st.set_page_config(
page_title="Hackathon Project Evaluator",
page_icon="🏆",
layout="wide"
)
# Create Vision Analysis Agent
@st.cache_resource
def get_hackathon_judge():
return Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
hackathon_judge = get_hackathon_judge()
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
elif isinstance(response, str):
evaluation_data = json.loads(response)
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
# Title and description
st.title("🏆 Hackathon Judge Agent")
st.markdown("""
Upload your hackathon project demonstration video for an AI-powered evaluation.
Get comprehensive feedback on various aspects of your project.
""")
# File uploader
uploaded_file = st.file_uploader("Choose a video file", type=['mp4', 'avi', 'mov', 'mkv'])
if uploaded_file:
# Create a temporary file to store the video
with tempfile.NamedTemporaryFile(delete=False, suffix='.'+uploaded_file.name.split('.')[-1]) as tmp_file:
tmp_file.write(uploaded_file.getvalue())
video_path = tmp_file.name
with st.spinner("🤖 AI is evaluating your project..."):
try:
# Evaluate the project
result = evaluate_project(video_path)
# Display results
st.header("Overall Score")
st.metric("Overall Score", f"{result.overall_score}/100")
# Display detailed scores
st.header("Detailed Scores")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Innovation", f"{result.innovation_score}/100")
st.metric("Technical Complexity", f"{result.technical_complexity}/100")
with col2:
st.metric("Presentation", f"{result.presentation_quality}/100")
st.metric("User Experience", f"{result.user_experience}/100")
with col3:
st.metric("Completeness", f"{result.completeness}/100")
# Display qualitative feedback
st.header("Key Strengths")
for strength in result.key_strengths:
st.write(f"• {strength}")
st.header("Areas for Improvement")
for area in result.areas_for_improvement:
st.write(f"• {area}")
st.header("Technical Highlights")
for highlight in result.technical_highlights:
st.write(f"• {highlight}")
st.header("Notable Features")
for feature in result.notable_features:
st.write(f"• {feature}")
st.header("Recommendations")
for rec in result.recommendations:
st.write(f"• {rec}")
# Market Analysis
st.header("Market Analysis")
col1, col2 = st.columns(2)
with col1:
st.subheader("Market Potential")
st.write(result.market_potential)
with col2:
st.subheader("Scalability Assessment")
st.write(result.scalability_assessment)
except Exception as e:
st.error(f"Error evaluating the project: {str(e)}")
finally:
# Clean up the temporary file
os.unlink(video_path)
else:
# Display placeholder content
st.info("👆 Upload a video file to get started!")
-47
View File
@@ -1,47 +0,0 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo])
agent.start("I want to go London next week, find me a good hotel and flight")
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create Image Analysis Agent
image_agent = Agent(
name="ImageAnalyst",
role="Image Analysis 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=image_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=image_agent,
images=["image.jpg"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[image_agent],
tasks=[task1, task2],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
-47
View File
@@ -1,47 +0,0 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo])
agent.start("I want to go London next week, find me a good hotel and flight")
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create Image Analysis Agent
image_agent = Agent(
name="ImageAnalyst",
role="Image Analysis 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=image_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=image_agent,
images=["image.jpg"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[image_agent],
tasks=[task1, task2],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.
-70
View File
@@ -1,70 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import logging
import os
import json
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# Define the configuration for the Knowledge instance
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Create an agent with knowledge capabilities
knowledge_agent = Agent(
name="KnowledgeAgent",
role="Information Specialist",
goal="Store and retrieve knowledge efficiently",
backstory="Expert in managing and utilizing stored knowledge",
verbose=True
)
# Define a task for the agent
knowledge_task = Task(
name="knowledge_task",
description="KAG",
expected_output="Answer to the question",
agent=knowledge_agent,
context=[
{
"embedding_db_config": json.dumps(config["vector_store"])
}
]
)
# Create and start the agents
agents = PraisonAIAgents(
agents=[knowledge_agent],
tasks=[knowledge_task],
process="sequential",
user_id="user1"
)
# Start execution
result = agents.start()
-21
View File
@@ -1,21 +0,0 @@
from praisonaiagents import Agent
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison",
}
}
}
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["large.pdf"],
knowledge_config=config,
user_id="user1"
)
agent.start("What is KAG in one line?")
-44
View File
@@ -1,44 +0,0 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
knowledge = Knowledge(config)
# Search for memories based on a query
query = "KAG"
logger.info(f"Searching for memories with query: {query}")
search_results = knowledge.search(query, user_id="user1")
logger.info(f"Search results: {search_results}")
print(f"\nSearch results for '{query}':")
print(search_results)
-171
View File
@@ -1,171 +0,0 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "test",
"path": ".praison",
}
}
}
knowledge = Knowledge(config)
# Store memories
logger.info("Storing memories...")
cricket_memory = knowledge.store("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
logger.info(f"Stored cricket memory: {cricket_memory}")
tennis_memory = knowledge.store("Enjoys playing tennis with friends", user_id="alice", metadata={"category": "hobbies"})
logger.info(f"Stored tennis memory: {tennis_memory}")
work_memory = knowledge.store("Works as a software engineer", user_id="alice", metadata={"category": "work"})
logger.info(f"Stored work memory: {work_memory}")
print("Stored memories:")
print(cricket_memory)
print(tennis_memory)
print(work_memory)
# Retrieve all memories for a user
logger.info("Retrieving all memories for Alice...")
alice_memories = knowledge.get_all(user_id="alice")
logger.info(f"Retrieved memories for Alice: {alice_memories}")
print("\nAll memories for Alice:")
for memory in alice_memories:
print(memory)
# Retrieve a specific memory by ID
logger.info(f"Retrieving memory with ID: {cricket_memory['results'][0]['id']}")
retrieved_memory = knowledge.get(cricket_memory['results'][0]["id"])
logger.info(f"Retrieved memory: {retrieved_memory}")
print("\nRetrieved memory:")
print(retrieved_memory)
# Search for memories based on a query
query = "What are Alice's hobbies?"
logger.info(f"Searching for memories with query: {query}")
search_results = knowledge.search(query, user_id="alice")
logger.info(f"Search results: {search_results}")
print(f"\nSearch results for '{query}':")
for memory in search_results:
print(memory)
# Update a memory
logger.info(f"Updating memory with ID: {tennis_memory['results'][0]['id']}")
updated_memory = knowledge.update(memory_id=tennis_memory['results'][0]["id"], data="Loves playing tennis on weekends")
logger.info(f"Updated memory: {updated_memory}")
print("\nUpdated memory:")
print(updated_memory)
# Get memory history
logger.info(f"Retrieving memory history for ID: {tennis_memory['results'][0]['id']}")
memory_history = knowledge.history(memory_id=tennis_memory['results'][0]["id"])
logger.info(f"Memory history: {memory_history}")
print("\nMemory history:")
for entry in memory_history:
print(entry)
# Delete a memory
logger.info(f"Deleting memory with ID: {work_memory['results'][0]['id']}")
knowledge.delete(memory_id=work_memory['results'][0]["id"])
logger.info("Memory deleted")
print("\nDeleted memory")
# Retrieve memories after deletion
logger.info("Retrieving memories after deletion...")
alice_memories = knowledge.get_all(user_id="alice")
logger.info(f"Retrieved memories after deletion: {alice_memories}")
print("\nMemories after deletion:")
for memory in alice_memories:
print(memory)
# Delete all memories for a user
logger.info("Deleting all memories for Alice...")
knowledge.delete_all(user_id="alice")
logger.info("All memories for Alice deleted")
print("\nAll memories for Alice deleted")
# Retrieve memories after deleting all
logger.info("Retrieving memories after deleting all...")
alice_memories = knowledge.get_all(user_id="alice")
logger.info(f"Retrieved memories after deleting all: {alice_memories}")
print("\nMemories after deleting all:")
print(alice_memories)
# Reset all memories
logger.info("Resetting all memories...")
knowledge.reset()
logger.info("All memories reset")
print("\nAll memories reset")
# Test file handling
logger.info("Testing file handling...")
try:
# Get absolute path to test files
current_dir = os.path.dirname(os.path.abspath(__file__))
pdf_file = os.path.join(current_dir, "small.pdf")
txt_file = os.path.join(current_dir, "sample.txt")
# Test text file
logger.info(f"Testing text file: {txt_file}")
# Read and display content
with open(txt_file, 'r') as file:
txt_content = file.read()
print("\nText file content:")
print(txt_content)
# Store the text file using add
txt_memory = knowledge.add(txt_file, user_id="bob", metadata={"type": "text"})
logger.info(f"Stored text file: {txt_memory}")
print("\nStored text content:")
if txt_memory and 'results' in txt_memory and txt_memory['results']:
for mem in txt_memory['results']:
print(mem)
else:
print("No valid memories were stored from the text file")
# Verify text memories are stored
if txt_memory and 'results' in txt_memory and txt_memory['results']:
logger.info("Verifying text memories...")
for mem in txt_memory['results']:
if isinstance(mem, dict) and 'id' in mem:
stored = knowledge.get(mem['id'])
logger.info(f"Verified text memory: {stored}")
else:
logger.warning(f"Unexpected memory format: {mem}")
else:
logger.warning("No valid memories were stored from the text file")
# Test pdf file
logger.info(f"Testing pdf file: {pdf_file}")
pdf_memory = knowledge.add(pdf_file, user_id="bob", metadata={"type": "pdf"})
logger.info(f"Stored pdf file: {pdf_memory}")
print("\nStored pdf content:")
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for mem in pdf_memory['results']:
print(mem)
else:
print("No valid memories were stored from the PDF file")
# Verify stored content
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for memory in pdf_memory['results']:
if isinstance(memory, dict) and 'id' in memory:
stored_memory = knowledge.get(memory['id'])
logger.info(f"Verified stored memory: {stored_memory}")
print("\nVerified content:")
print(stored_memory)
else:
logger.warning(f"Unexpected memory format: {memory}")
else:
logger.warning("No valid memories were stored from the PDF file")
except Exception as e:
logger.error(f"Error during file handling test: {str(e)}")
raise
-40
View File
@@ -1,40 +0,0 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
knowledge = Knowledge()
try:
# Get absolute path to test files
current_dir = os.path.dirname(os.path.abspath(__file__))
pdf_file = os.path.join(current_dir, "large.pdf")
# Test pdf file
logger.info(f"Testing pdf file: {pdf_file}")
pdf_memory = knowledge.add(pdf_file, user_id="bob", metadata={"type": "pdf"})
logger.info(f"Stored pdf file: {pdf_memory}")
print("\nStored pdf content:")
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for mem in pdf_memory['results']:
print(mem)
else:
print("No valid memories were stored from the PDF file")
# Verify stored content
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for memory in pdf_memory['results']:
if isinstance(memory, dict) and 'id' in memory:
stored_memory = knowledge.get(memory['id'])
logger.info(f"Verified stored memory: {stored_memory}")
print("\nVerified content:")
print(stored_memory)
else:
logger.warning(f"Unexpected memory format: {memory}")
else:
logger.warning("No valid memories were stored from the PDF file")
except Exception as e:
logger.error(f"Error during file handling test: {str(e)}")
raise
-30
View File
@@ -1,30 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from langchain_community.tools import YouTubeSearchTool
from langchain_community.utilities import WikipediaAPIWrapper
# Create an agent with both tools
agent = Agent(
name="SearchAgent",
role="Research Assistant",
goal="Search for information from multiple sources",
backstory="I am an AI assistant that can search YouTube and Wikipedia.",
tools=[YouTubeSearchTool, WikipediaAPIWrapper],
self_reflect=False
)
# Create tasks to demonstrate both tools
task = Task(
name="search_task",
description="Search for information about 'AI advancements' on both YouTube and Wikipedia",
expected_output="Combined information from YouTube videos and Wikipedia articles",
agent=agent
)
# Create and start the workflow
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
verbose=True
)
agents.start()
-73
View File
@@ -1,73 +0,0 @@
from langchain_community.tools import YouTubeSearchTool
from langchain_community.utilities import WikipediaAPIWrapper
def test_tools():
"""Test both YouTube and Wikipedia tools"""
print("\n=== Testing YouTube Search ===")
# Test YouTube
yt = YouTubeSearchTool()
# Test basic search
print("\nBasic YouTube Search:")
query = "AI advancements 2024"
print(f"Query: {query}")
result = yt.run(query)
print(f"Results: {result}")
# Test with max results
print("\nYouTube Search with max results:")
query = "AI advancements 2024, 3" # Format: query, max_results
print(f"Query: {query}")
result = yt.run(query)
print(f"Results: {result}")
print("\n=== Testing Wikipedia Search ===")
# Test Wikipedia
wiki = WikipediaAPIWrapper(
top_k_results=2,
doc_content_chars_max=500
)
# Test basic search
print("\nBasic Wikipedia Search:")
query = "Artificial Intelligence"
print(f"Query: {query}")
result = wiki.run(query)
print(f"Results: {result[:200]}..." if result else "No result")
# Test with different parameters
print("\nWikipedia Search with different language:")
wiki_fr = WikipediaAPIWrapper(
lang='fr',
top_k_results=1,
doc_content_chars_max=300
)
result = wiki_fr.run("Intelligence Artificielle")
print(f"French Results: {result[:200]}..." if result else "No result")
def print_tool_info():
"""Print detailed information about the tools"""
print("\n=== Tool Information ===")
# YouTube Tool Info
print("\nYouTube Tool:")
yt = YouTubeSearchTool()
print("Type:", type(yt))
print("Name:", getattr(yt, 'name', None))
print("Description:", getattr(yt, 'description', None))
print("Arguments:", getattr(yt, 'args', None))
# Wikipedia Tool Info
print("\nWikipedia Tool:")
wiki = WikipediaAPIWrapper()
print("Type:", type(wiki))
print("Available Settings:")
print("- Language:", wiki.lang)
print("- Top K Results:", wiki.top_k_results)
print("- Max Characters:", wiki.doc_content_chars_max)
if __name__ == "__main__":
print_tool_info()
test_tools()
BIN
View File
Binary file not shown.
View File
Whitespace-only changes.
-4
View File
@@ -1,4 +0,0 @@
from praisonaiagents import Agent
agent = Agent(instructions="You are a Markdown Agent, output in markdown format")
agent.start("Write a blog post about AI")
-5
View File
@@ -1,5 +0,0 @@
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert("sample.txt")
print(result.text_content)
-220
View File
@@ -1,220 +0,0 @@
from mem0 import Memory
import logging
import json
import os
import time
from datetime import datetime
from typing import Dict, Any, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MemoryManager:
def __init__(self):
"""Initialize Mem0 Memory manager with configuration"""
# Define the complete configuration with only supported fields
config = {
"version": "v1.1",
"custom_prompt": None,
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Ensure storage directory exists
storage_path = os.path.abspath("./.praison/storage")
if os.path.exists(storage_path):
logger.info(f"Clearing existing storage at {storage_path}")
import shutil
shutil.rmtree(storage_path)
os.makedirs(storage_path, exist_ok=True)
logger.info(f"Created storage path: {storage_path}")
# Initialize memory
self.memory = Memory.from_config(config)
logger.info("Memory manager initialized")
def pretty_print(self, data: Any) -> None:
"""Helper function to print memory data in a readable format"""
if isinstance(data, (dict, list)):
print(json.dumps(data, indent=2))
else:
print(data)
def extract_memory_id(self, result: Any) -> Optional[str]:
"""Extract memory ID from the result, handling different formats"""
try:
if isinstance(result, dict):
# v1.1 format
memories = result.get('results', [])
return memories[0]['id'] if memories else None
elif isinstance(result, list):
# v1.0 format
return result[0]['id'] if result else None
return None
except (KeyError, IndexError) as e:
logger.warning(f"Could not extract memory ID from result: {e}")
return None
def prepare_metadata(self, metadata: Optional[Dict]) -> Dict:
"""Prepare metadata by converting values to acceptable types"""
if not metadata:
return {}
clean_metadata = {}
for key, value in metadata.items():
if isinstance(value, (str, int, float, bool)):
clean_metadata[key] = value
elif isinstance(value, list):
clean_metadata[key] = ','.join(map(str, value))
elif isinstance(value, dict):
clean_metadata[key] = json.dumps(value)
else:
clean_metadata[key] = str(value)
return clean_metadata
def verify_memory_addition(self, user_id: str, max_retries: int = 3) -> bool:
"""Verify that memory was added successfully"""
for attempt in range(max_retries):
try:
time.sleep(0.5) # Brief pause to allow indexing
memories = self.memory.get_all(user_id=user_id)
if len(memories.get('results', [])) > 0:
return True
logger.warning(f"Memory not found on attempt {attempt + 1}")
except Exception as e:
logger.warning(f"Verification attempt {attempt + 1} failed: {e}")
if attempt < max_retries - 1:
time.sleep(1)
return False
def add_memory(self, text: str, user_id: Optional[str] = None, metadata: Optional[Dict] = None) -> Dict:
"""Add a new memory with error handling and verification"""
try:
logger.info(f"Adding memory for user {user_id}")
clean_metadata = self.prepare_metadata(metadata)
logger.debug(f"Prepared metadata: {clean_metadata}")
messages = [{"role": "user", "content": text}]
result = self.memory.add(
messages=messages,
user_id=user_id,
metadata=clean_metadata
)
if self.verify_memory_addition(user_id):
logger.info("Memory added and verified successfully")
else:
logger.warning("Memory addition could not be verified")
return result
except Exception as e:
logger.error(f"Failed to add memory: {str(e)}")
raise
def get_all_memories(self, user_id: Optional[str] = None) -> Dict:
"""Retrieve all memories for a user"""
try:
logger.info(f"Retrieving all memories for user {user_id}")
memories = self.memory.get_all(user_id=user_id)
count = len(memories.get('results', []))
logger.info(f"Retrieved {count} memories")
return memories
except Exception as e:
logger.error(f"Failed to retrieve memories: {str(e)}")
raise
def search_memories(self, query: str, user_id: Optional[str] = None, limit: int = 5) -> Dict:
"""Search memories with a query"""
try:
logger.info(f"Searching memories with query: {query}")
results = self.memory.search(
query=query,
user_id=user_id,
limit=limit
)
count = len(results.get('results', []))
logger.info(f"Found {count} matching memories")
return results
except Exception as e:
logger.error(f"Search failed: {str(e)}")
raise
def main():
try:
# Initialize memory manager
manager = MemoryManager()
# Add a test memory
print("\n1. Adding a new memory:")
metadata = {
"category": "hobbies",
"timestamp": datetime.now().isoformat(),
"tags": "tennis,learning",
"priority": 1,
"source": "user_input"
}
result = manager.add_memory(
text="I am working on improving my tennis skills. Suggest some online courses.",
user_id="alice",
metadata=metadata
)
manager.pretty_print(result)
# Wait briefly for indexing
time.sleep(1)
print("\n2. Retrieving all memories:")
all_memories = manager.get_all_memories(user_id="alice")
manager.pretty_print(all_memories)
print("\n3. Searching memories:")
search_results = manager.search_memories(
query="What are Alice's hobbies?",
user_id="alice",
limit=5
)
manager.pretty_print(search_results)
# Print summary
print("\nMemory Store Summary:")
total_memories = len(all_memories.get('results', []))
print(f"Total memories stored: {total_memories}")
if total_memories > 0:
print("Available memories:")
for mem in all_memories['results']:
print(f"- {mem.get('memory', 'No content')}")
except Exception as e:
logger.error(f"Main process failed: {str(e)}", exc_info=True)
raise
if __name__ == "__main__":
main()
-143
View File
@@ -1,143 +0,0 @@
from mem0 import Memory
import logging
import json
import os
from typing import Dict, Any, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MemorySearcher:
def __init__(self):
"""Initialize Mem0 Memory searcher with configuration"""
# Define the configuration
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Initialize memory
self.memory = Memory.from_config(config)
logger.info("Memory searcher initialized")
def pretty_print(self, data: Any) -> None:
"""Helper function to print data in a readable format"""
if isinstance(data, (dict, list)):
print(json.dumps(data, indent=2))
else:
print(data)
def get_all_memories(self, user_id: Optional[str] = None) -> Dict:
"""Retrieve all memories for a user"""
try:
logger.info(f"Retrieving all memories for user {user_id}")
memories = self.memory.get_all(user_id=user_id)
count = len(memories.get('results', []))
logger.info(f"Retrieved {count} memories")
return memories
except Exception as e:
logger.error(f"Failed to retrieve memories: {str(e)}")
raise
def search_memories(self, query: str, user_id: Optional[str] = None, limit: int = 5) -> Dict:
"""Search memories with a query"""
try:
logger.info(f"Searching memories with query: {query}")
results = self.memory.search(
query=query,
user_id=user_id,
limit=limit
)
count = len(results.get('results', []))
logger.info(f"Found {count} matching memories")
return results
except Exception as e:
logger.error(f"Search failed: {str(e)}")
raise
def list_unique_users(self) -> list:
"""List all unique users in the memory store"""
try:
all_memories = self.memory.get_all()
users = set()
for memory in all_memories.get('results', []):
if 'user_id' in memory:
users.add(memory['user_id'])
return sorted(list(users))
except Exception as e:
logger.error(f"Failed to list users: {str(e)}")
raise
def main():
try:
# Initialize memory searcher
searcher = MemorySearcher()
# Get list of users
print("\n1. Available users in the memory store:")
users = searcher.list_unique_users()
searcher.pretty_print(users)
if not users:
print("No users found in the memory store. Please add some memories first.")
return
# Example user (using first user found)
example_user = users[0]
print(f"\n2. All memories for user '{example_user}':")
all_memories = searcher.get_all_memories(user_id=example_user)
searcher.pretty_print(all_memories)
print(f"\n3. Searching memories for user '{example_user}':")
search_results = searcher.search_memories(
query="What are their hobbies?",
user_id=example_user,
limit=5
)
searcher.pretty_print(search_results)
# Print summary
print("\nMemory Store Summary:")
total_memories = len(all_memories.get('results', []))
print(f"Total memories for {example_user}: {total_memories}")
if total_memories > 0:
print("Available memories:")
for mem in all_memories['results']:
print(f"- {mem.get('memory', 'No content')}")
if 'metadata' in mem:
print(f" Metadata: {mem['metadata']}")
except Exception as e:
logger.error(f"Main process failed: {str(e)}", exc_info=True)
raise
if __name__ == "__main__":
main()
-26
View File
@@ -1,26 +0,0 @@
from mem0 import Memory
import os
import json
# Basic configuration
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison",
}
}
}
# Initialize memory
memory = Memory.from_config(config)
# Search Alice's hobbies
search_results = memory.search(
query="KAG",
user_id="user1",
limit=5
)
print(search_results)
-46
View File
@@ -1,46 +0,0 @@
from mem0 import Memory
import os
import json
# Basic configuration
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage")
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini"
}
}
}
# Initialize memory
memory = Memory.from_config(config)
# Search Alice's hobbies
search_results = memory.search(
query="What are Alice's hobbies?",
user_id="alice",
limit=5
)
# Print results in a readable format
print("\nAlice's Memories:")
for memory in search_results['results']:
print(f"\nMemory: {memory['memory']}")
print(f"Score: {memory['score']}")
if 'metadata' in memory:
print("Metadata:")
print(json.dumps(memory['metadata'], indent=2))
-183
View File
@@ -1,183 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import logging
import os
def main():
# Initialize memory config
memory_config = {
"provider": "rag",
"use_embedding": True,
"storage": {
"type": "sqlite",
"path": "./.praison/memory.db"
},
"rag_db_path": "./.praison/chroma_db"
}
# Test facts
fact1 = "The capital city of Jujuha is Hahanu and its population is 102300"
fact2 = "Three main ingredients in a classic proloder are eggs, sugar, and flour"
fact3 = "The year the first Josinga was released is 2007"
# # Check if database exists
# if os.path.exists("./memory.db"):
# logger.info("Found existing memory database")
# else:
# logger.info("Creating new memory database")
# Create task config (without memory config since it's moved to PraisonAIAgents)
task_config = {}
# Create agents with different roles
researcher = Agent(
role="Research Analyst",
goal="Research and document key information about topics",
backstory="Expert at analyzing and storing information in memory",
llm="gpt-4o-mini"
)
retriever = Agent(
role="Information Retriever",
goal="Retrieve and verify stored information from memory",
backstory="Specialist in searching and validating information from memory",
llm="gpt-4o-mini"
)
# Task 1: Process the facts
store_task = Task(
description=f"""
Process and analyze this information:
1. {fact1}
2. {fact2}
3. {fact3}
Provide a clear summary of each fact.
""",
expected_output="""
Clear statements summarizing each fact.
Example format:
1. [Summary of fact 1]
2. [Summary of fact 2]
3. [Summary of fact 3]
""",
agent=researcher
)
# Task 2: Write essay about AI
verify_task = Task(
description="""
write few points about AI
""",
expected_output="Points about AI",
agent=retriever
)
# Task 3: Query memory
query_task = Task(
description="""
Using ONLY information found in memory:
1. What is stored in memory about Hahanu?
2. What ingredients for proloder are recorded in memory?
3. What year is stored in memory for the Josinga release?
For each answer, cite the memory record you found.
""",
expected_output="Answers based solely on memory records with citations",
agent=retriever
)
# Task 4: Query both short-term and long-term memory
query_both_task = Task(
description="""
Using ONLY information found in memory:
1. What is stored in both short-term and long-term memory about Jujuha?
2. What ingredients for proloder are recorded in both short-term and long-term memory?
3. What year is stored in both short-term and long-term memory for the Josinga release?
For each answer, cite the memory record you found.
""",
expected_output="Answers based solely on memory records with citations",
agent=retriever
)
# Initialize PraisonAIAgents with memory configuration
agents = PraisonAIAgents(
agents=[researcher, retriever],
tasks=[store_task, verify_task, query_task, query_both_task],
verbose=True, # Use same verbose level as memory
memory=True,
embedder={
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
}
)
# agents = PraisonAIAgents(
# agents=[researcher, retriever],
# tasks=[store_task, verify_task, query_task, query_both_task],
# verbose=True, # Use same verbose level as memory
# memory=True
# )
# Execute tasks
print("\nExecuting Memory Test Tasks...")
print("-" * 50)
agents.start()
# Use shared memory for final checks
memory = agents.shared_memory
# Test memory retrieval with different quality thresholds
if memory:
print("\nFinal Memory Check:")
print("-" * 50)
queries = ["Jujuha", "proloder", "Josinga"]
for query in queries:
print(f"\nSearching memory for: {query}")
# Search in both short-term and long-term memory
print("\nShort-term memory results:")
stm_results = memory.search_short_term(query)
if stm_results:
for item in stm_results:
print(f"Content: {item.get('content', '')[:200]}")
if 'meta' in item:
print(f"Metadata: {item['meta']}")
print("-" * 20)
else:
print("No results found in short-term memory")
print("\nLong-term memory results:")
ltm_results = memory.search_long_term(query)
if ltm_results:
for item in ltm_results:
print(f"Content: {item.get('text', '')[:200]}")
if 'metadata' in item:
print(f"Metadata: {item['metadata']}")
print("-" * 20)
else:
print("No results found in long-term memory")
# Also check ChromaDB if using RAG
if memory.use_rag and hasattr(memory, "chroma_col"):
print("\nChromaDB results:")
try:
all_items = memory.chroma_col.get()
print(f"Found {len(all_items['ids'])} items in ChromaDB")
for i in range(len(all_items['ids'])):
print(f"ID: {all_items['ids'][i]}")
print(f"Content: {all_items['documents'][i][:200]}")
print(f"Metadata: {all_items['metadatas'][i]}")
print("-" * 20)
except Exception as e:
print(f"Error querying ChromaDB: {e}")
print("-" * 30)
else:
print("\nNo memory available for final checks")
if __name__ == "__main__":
main()
-63
View File
@@ -1,63 +0,0 @@
from praisonaiagents.agents.agents import Agent, Task, PraisonAIAgents
from praisonaiagents.tools import duckduckgo
# Test facts
fact1 = "The capital city of Jujuha is Hahanu and its population is 102300"
fact2 = "Three main ingredients in a classic proloder are eggs, sugar, and flour"
fact3 = "The year the first Josinga was released is 2007"
fact_agent = Agent(
name="Fact Agent",
instructions="You are a fact agent, you store and retrieve facts in memory",
llm="gpt-4o-mini"
)
research_agent = Agent(
name="Research Agent",
instructions="You are a research analyst, you research and document key points about topics",
llm="gpt-4o-mini"
)
blog_agent = Agent(
name="Blog Agent",
instructions="You are a blog writer, you write a blog post about the research",
llm="gpt-4o-mini"
)
fact_task = Task(
description="Store the following facts in memory: " + fact1 + ", " + fact2 + ", " + fact3,
agent=fact_agent
)
research_task = Task(
description="Research and document 2 key points about AI",
agent=research_agent
)
research_task2 = Task(
description="Research and document 2 key points about AI in healthcare",
agent=research_agent
)
research_task3 = Task(
description="Research and document 2 key points about AI in education",
agent=research_agent
)
research_task4 = Task(
description="Research and document 2 key points about AI in finance",
agent=research_agent
)
blog_task = Task(
description="Write a blog post about Jujuha",
agent=blog_agent
)
agents = PraisonAIAgents(
agents=[fact_agent, research_agent, blog_agent],
tasks=[fact_task, research_task, research_task2, research_task3, research_task4, blog_task],
memory=True
)
agents.start()
-6
View File
@@ -1,6 +0,0 @@
from praisonaiagents import Agent, Agents, Tools
research_agent = Agent(instructions="You are a research agent to search internet about AI 2024", tools=[Tools.internet_search])
summarise_agent = Agent(instructions="You are a summarize agent to summarise in points")
agents = Agents(agents=[research_agent, summarise_agent])
agents.start()
-54
View File
@@ -1,54 +0,0 @@
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
agents.start()
-110
View File
@@ -1,110 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
def get_time_check():
current_time = int(time.time())
if current_time % 3 == 0:
result = 1
elif current_time % 3 == 1:
result = 2
else:
result = 3
print(f"Time: {current_time}, Result: {result}")
return result
# Create orchestrator and worker agents
router = Agent(
name="Router",
role="Task router",
goal="Distribute tasks to based on response from get_time_check",
tools=[get_time_check]
)
worker1 = Agent(
name="Worker 1",
role="Specialized worker",
goal="Handle specific subtask type 1",
)
worker2 = Agent(
name="Worker 2",
role="Specialized worker",
goal="Handle specific subtask type 2",
)
worker3 = Agent(
name="Worker 3",
role="Specialized worker",
goal="Handle specific subtask type 3",
)
synthesizer = Agent(
name="Synthesizer",
role="Result synthesizer",
goal="Combine and synthesize worker outputs",
)
# Create orchestrated workflow tasks
router_task = Task(
name="route_task",
description="Analyze input from get_time_check and route to appropriate workers",
expected_output="Task routing decision, 1 , 2 or 3",
agent=router,
is_start=True,
task_type="decision",
next_tasks=["worker1_task", "worker2_task", "worker3_task"],
condition={
"1": ["worker1_task"],
"2": ["worker2_task"],
"3": ["worker3_task"]
}
)
worker1_task = Task(
name="worker1_task",
description="Process type 1 operation",
expected_output="Worker 1 result",
agent=worker1,
next_tasks=["synthesize_task"]
)
worker2_task = Task(
name="worker2_task",
description="Process type 2 operation",
expected_output="Worker 2 result",
agent=worker2,
next_tasks=["synthesize_task"]
)
worker3_task = Task(
name="worker3_task",
description="Process type 3 operation",
expected_output="Worker 3 result",
agent=worker3,
next_tasks=["synthesize_task"]
)
synthesize_task = Task(
name="synthesize_task",
description="Synthesize worker results into final output",
expected_output="Final synthesized result",
agent=synthesizer,
context=[worker1_task, worker2_task, worker3_task]
)
# Create workflow manager
workflow = PraisonAIAgents(
agents=[router, worker1, worker2, worker3, synthesizer],
tasks=[router_task, worker1_task, worker2_task, worker3_task, synthesize_task],
process="workflow",
verbose=True
)
# Run orchestrated workflow
results = workflow.start()
# Print results
print("\nOrchestrator-Workers Results:")
for task_id, result in results["task_results"].items():
if result:
print(f"Task {task_id}: {result.raw}")
-95
View File
@@ -1,95 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from datetime import datetime
import asyncio
def process_time():
"""Simulate processing"""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"Processing at: {current_time}")
return f"Processed at {current_time}"
# Create parallel processing agents
agent1 = Agent(
name="Processor 1",
role="Time collector",
goal="Get the time and return it",
tools=[process_time]
)
agent2 = Agent(
name="Processor 2",
role="Time collector",
goal="Get the time and return it",
tools=[process_time]
)
agent3 = Agent(
name="Processor 3",
role="Time collector",
goal="Get the time and return it",
tools=[process_time]
)
aggregator = Agent(
name="Aggregator",
role="Result aggregator",
goal="Collect all the processed time from all tasks"
)
# Create parallel tasks with memory disabled
task1 = Task(
name="process_1",
description="Use process_time tool to get the time",
expected_output="processed time",
agent=agent1,
is_start=True,
async_execution=True
)
task2 = Task(
name="process_2",
description="Use process_time tool to get the time",
expected_output="processed time",
agent=agent2,
is_start=True,
async_execution=True
)
task3 = Task(
name="process_3",
description="Use process_time tool to get the time",
expected_output="processed time",
agent=agent3,
is_start=True,
async_execution=True
)
aggregate_task = Task(
name="aggregate",
description="Collect all the processed time from all tasks",
expected_output="Output all the processed time from all tasks and just the time",
agent=aggregator,
context=[task1, task2, task3]
)
async def main():
# Create workflow manager
workflow = PraisonAIAgents(
agents=[agent1, agent2, agent3, aggregator],
tasks=[task1, task2, task3, aggregate_task],
process="workflow"
)
# Run parallel workflow
results = await workflow.astart()
# Print results
print("\nParallel Processing Results:")
for task_id, result in results["task_results"].items():
if result:
print(f"Task {task_id}: {result.raw}")
# Run the async main function
if __name__ == "__main__":
asyncio.run(main())
-41
View File
@@ -1,41 +0,0 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create PDF Analysis Agent
pdf_agent = Agent(
name="PDFAnalyst",
role="PDF Document Specialist",
goal="Analyze PDF documents to extract meaningful information",
backstory="""You are an expert in PDF document analysis and text extraction.
You excel at understanding document structure, extracting content, and analyzing textual information.""",
llm="gpt-4o-mini",
self_reflect=False
)
# 1. Task with PDF URL
task1 = Task(
name="analyze_pdf_url",
description="Extract and analyze content from this PDF document.",
expected_output="Detailed analysis of the PDF content and structure",
agent=pdf_agent,
input=["https://example.com/document.pdf"]
)
# 2. Task with Local PDF File
task2 = Task(
name="analyze_local_pdf",
description="What information can you extract from this PDF? Analyze its content.",
expected_output="Detailed analysis of the PDF content and structure",
agent=pdf_agent,
input=["document.pdf"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[pdf_agent],
tasks=[task1, task2],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
-5
View File
@@ -1,5 +0,0 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Planning Agent", tools=[duckduckgo])
agent.start("I want to go London next week, find me a good hotel and flight")
-53
View File
@@ -1,53 +0,0 @@
"""
Praison AI Agents - A package for hierarchical AI agent task execution
"""
from .agent.agent import Agent
from .agents.agents import PraisonAIAgents
from .task.task import Task
from .tools.tools import Tools
from .agents.autoagents import AutoAgents
from .knowledge.knowledge import Knowledge
from .knowledge.chunking import Chunking
from .main import (
TaskOutput,
ReflectionOutput,
display_interaction,
display_self_reflection,
display_instruction,
display_tool_call,
display_error,
display_generating,
clean_triple_backticks,
error_logs,
register_display_callback,
sync_display_callbacks,
async_display_callbacks,
)
# Add Agents as an alias for PraisonAIAgents
Agents = PraisonAIAgents
__all__ = [
'Agent',
'PraisonAIAgents',
'Agents',
'Tools',
'Task',
'TaskOutput',
'ReflectionOutput',
'AutoAgents',
'display_interaction',
'display_self_reflection',
'display_instruction',
'display_tool_call',
'display_error',
'display_generating',
'clean_triple_backticks',
'error_logs',
'register_display_callback',
'sync_display_callbacks',
'async_display_callbacks',
'Knowledge',
'Chunking'
]
-4
View File
@@ -1,4 +0,0 @@
"""Agent module for AI agents"""
from .agent import Agent
__all__ = ['Agent']
File diff suppressed because it is too large. Load diff
@@ -1,5 +0,0 @@
"""Agents module for managing multiple AI agents"""
from .agents import PraisonAIAgents
from .autoagents import AutoAgents
__all__ = ['PraisonAIAgents', 'AutoAgents']
-851
View File
@@ -1,851 +0,0 @@
import os
import time
import json
import logging
from typing import Any, Dict, Optional, List
from pydantic import BaseModel
from rich.text import Text
from rich.panel import Panel
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
import uuid
# Set up logger
logger = logging.getLogger(__name__)
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=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None, memory=False, memory_config=None, embedder=None, user_id=None, max_iter=10):
# Add check at the start if memory is requested
if memory:
try:
from ..memory.memory import Memory
MEMORY_AVAILABLE = True
except ImportError:
raise ImportError(
"Memory features requested but memory dependencies not installed. "
"Please install with: pip install \"praisonaiagents[memory]\""
)
if not agents:
raise ValueError("At least one agent must be provided")
self.run_id = str(uuid.uuid4()) # Auto-generate run_id
self.user_id = user_id or "praison" # Optional user_id
self.max_iter = max_iter # Add max_iter parameter
# Pass user_id to each agent
for agent in agents:
agent.user_id = self.user_id
self.agents = agents
self.tasks = {}
if max_retries < 3:
max_retries = 3
self.completion_checker = completion_checker if completion_checker else self.default_completion_checker
self.task_id_counter = 0
self.verbose = verbose
self.max_retries = max_retries
self.process = process
# Check for manager_llm in environment variable if not provided
self.manager_llm = manager_llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
# Set logger level based on verbose
if verbose >= 5:
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.WARNING)
# Also set third-party loggers to WARNING
logging.getLogger('chromadb').setLevel(logging.WARNING)
logging.getLogger('openai').setLevel(logging.WARNING)
logging.getLogger('httpx').setLevel(logging.WARNING)
logging.getLogger('httpcore').setLevel(logging.WARNING)
if self.verbose:
logger.info(f"Using model {self.manager_llm} for manager")
# If no tasks provided, generate them from agents
if tasks is None:
tasks = []
for agent in self.agents:
task = agent.generate_task()
tasks.append(task)
logger.info(f"Auto-generated {len(tasks)} tasks from agents")
else:
# Validate tasks for backward compatibility
if not tasks:
raise ValueError("If tasks are provided, at least one task must be present")
logger.info(f"Using {len(tasks)} provided tasks")
# Add tasks and set their status
for task in tasks:
self.add_task(task)
task.status = "not started"
# If tasks were auto-generated from agents or process is sequential, set up sequential flow
if len(tasks) > 1 and (process == "sequential" or all(task.next_tasks == [] for task in tasks)):
for i in range(len(tasks) - 1):
# Set up next task relationship
tasks[i].next_tasks = [tasks[i + 1].name]
# Set up context for the next task to include the current task
if tasks[i + 1].context is None:
tasks[i + 1].context = []
tasks[i + 1].context.append(tasks[i])
logger.info("Set up sequential flow with automatic context passing")
self._state = {} # Add state storage at PraisonAIAgents level
# Initialize memory system
self.shared_memory = None
if memory:
try:
from ..memory.memory import Memory
# Get memory config from parameter or first task
mem_cfg = memory_config
if not mem_cfg:
mem_cfg = next((t.config.get('memory_config') for t in tasks if hasattr(t, 'config') and t.config), None)
# Set default memory config if none provided
if not mem_cfg:
mem_cfg = {
"provider": "rag",
"use_embedding": True,
"storage": {
"type": "sqlite",
"path": "./.praison/memory.db"
},
"rag_db_path": "./.praison/chroma_db"
}
# Add embedder config if provided
if embedder:
if isinstance(embedder, dict):
mem_cfg = mem_cfg or {}
mem_cfg["embedder"] = embedder
else:
# Handle direct embedder function
mem_cfg = mem_cfg or {}
mem_cfg["embedder_function"] = embedder
if mem_cfg:
# Pass verbose level to Memory
self.shared_memory = Memory(config=mem_cfg, verbose=verbose)
if verbose >= 5:
logger.info("Initialized shared memory for PraisonAIAgents")
# Distribute memory to tasks
for task in tasks:
if not task.memory:
task.memory = self.shared_memory
if verbose >= 5:
logger.info(f"Assigned shared memory to task {task.id}")
except Exception as e:
logger.error(f"Failed to initialize shared memory: {e}")
# Update tasks with shared memory
if self.shared_memory:
for task in tasks:
if not task.memory:
task.memory = self.shared_memory
logger.info(f"Assigned shared memory to task {task.id}")
def add_task(self, task):
task_id = self.task_id_counter
task.id = task_id
self.tasks[task_id] = task
self.task_id_counter += 1
return task_id
def clean_json_output(self, output: str) -> str:
cleaned = output.strip()
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
def default_completion_checker(self, task, agent_output):
if task.output_json and task.result and task.result.json_dict:
return True
if task.output_pydantic and task.result and task.result.pydantic:
return True
return len(agent_output.strip()) > 0
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
# Ensure tools are available from both task and agent
tools = task.tools or []
if executor_agent and executor_agent.tools:
tools.extend(executor_agent.tools)
task_prompt = f"""
You need to do the following task: {task.description}.
Expected Output: {task.expected_output}.
"""
if task.context:
context_results = [] # Use list to avoid duplicates
for context_item in task.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
elif isinstance(context_item, dict) and "vector_store" in context_item:
from ..knowledge.knowledge import Knowledge
try:
# Handle both string and dict configs
cfg = context_item["vector_store"]
if isinstance(cfg, str):
cfg = json.loads(cfg)
knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
# Only use user_id as filter
db_results = knowledge.search(
task.description,
user_id=self.user_id if self.user_id else None
)
context_results.append(f"[DB Context]: {str(db_results)}")
except Exception as e:
context_results.append(f"[Vector DB Error]: {e}")
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Context:
{' '.join(unique_contexts)}
"""
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
if self.verbose >= 2:
logger.info(f"Executing task {task_id}: {task.description} using {executor_agent.name}")
logger.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 = await executor_agent.achat(
_get_multimodal_message(task_prompt, task.images),
tools=tools,
output_json=task.output_json,
output_pydantic=task.output_pydantic
)
else:
agent_output = await executor_agent.achat(
task_prompt,
tools=tools,
output_json=task.output_json,
output_pydantic=task.output_pydantic
)
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:
logger.warning(f"Warning: Could not parse output of task {task_id} as JSON")
logger.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:
logger.warning(f"Warning: Could not parse output of task {task_id} as Pydantic Model")
logger.debug(f"Output that failed Pydantic parsing: {agent_output}")
task.result = task_output
return task_output
else:
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":
logger.info(f"Task with ID {task_id} is already completed")
return
retries = 0
while task.status != "completed" and retries < self.max_retries:
logger.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"
# Run execute_callback for memory operations
try:
try:
# If a loop is already running, just create the task
loop = asyncio.get_running_loop()
loop.create_task(task.execute_callback(task_output))
except RuntimeError:
# Otherwise, create and set a new loop, and run the callback
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.create_task(task.execute_callback(task_output))
except Exception as e:
logger.error(f"Error executing memory callback for task {task_id}: {e}")
logger.exception(e)
# Run task callback if exists
if task.callback:
try:
if asyncio.iscoroutinefunction(task.callback):
if asyncio.get_event_loop().is_running():
asyncio.create_task(task.callback(task_output))
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(task.callback(task_output))
else:
task.callback(task_output)
except Exception as e:
logger.error(f"Error executing task callback for task {task_id}: {e}")
logger.exception(e)
self.save_output_to_file(task, task_output)
if self.verbose >= 1:
logger.info(f"Task {task_id} completed successfully.")
else:
task.status = "in progress"
if self.verbose >= 1:
logger.info(f"Task {task_id} not completed, retrying")
await asyncio.sleep(1)
retries += 1
else:
if task.status == "failed":
logger.info("Task is failed, resetting to in-progress for another try...")
task.status = "in progress"
else:
logger.info("Invalid Task status")
break
if retries == self.max_retries and task.status != "completed":
logger.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,
max_iter=self.max_iter
)
if self.process == "workflow":
# Collect all tasks that should run in parallel
parallel_tasks = []
async for task_id in process.aworkflow():
if self.tasks[task_id].async_execution and self.tasks[task_id].is_start:
parallel_tasks.append(task_id)
elif parallel_tasks:
# Execute collected parallel tasks
await asyncio.gather(*[self.arun_task(t) for t in parallel_tasks])
parallel_tasks = []
# Run the current non-parallel task
if self.tasks[task_id].async_execution:
await self.arun_task(task_id)
else:
self.run_task(task_id)
# Execute any remaining parallel tasks
if parallel_tasks:
await asyncio.gather(*[self.arun_task(t) for t in parallel_tasks])
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, content=None, **kwargs):
"""Async version of start method"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
if not task.context:
task.context = []
task.context.append(content)
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:
if task.create_directory:
os.makedirs(os.path.dirname(task.output_file), exist_ok=True)
with open(task.output_file, "w") as f:
f.write(str(task_output))
if self.verbose >= 1:
logger.info(f"Task output saved to {task.output_file}")
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]
logger.info(f"Starting execution of task {task_id}")
logger.info(f"Task config: {task.config}")
# Initialize memory before task execution
if not task.memory:
task.memory = task.initialize_memory()
logger.info(f"Task memory status: {'Initialized' if task.memory else 'Not initialized'}")
# 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 = [] # Use list to avoid duplicates
for context_item in task.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
elif isinstance(context_item, dict) and "vector_store" in context_item:
from ..knowledge.knowledge import Knowledge
try:
# Handle both string and dict configs
cfg = context_item["vector_store"]
if isinstance(cfg, str):
cfg = json.loads(cfg)
knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
# Only use user_id as filter
db_results = knowledge.search(
task.description,
user_id=self.user_id if self.user_id else None
)
context_results.append(f"[DB Context]: {str(db_results)}")
except Exception as e:
context_results.append(f"[Vector DB Error]: {e}")
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Context:
{' '.join(unique_contexts)}
"""
# Add memory context if available
if task.memory:
try:
memory_context = task.memory.build_context_for_task(task.description)
if memory_context:
task_prompt += f"\n\nRelevant memory context:\n{memory_context}"
except Exception as e:
logger.error(f"Error getting memory context: {e}")
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
if self.verbose >= 2:
logger.info(f"Executing task {task_id}: {task.description} using {executor_agent.name}")
logger.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,
output_json=task.output_json,
output_pydantic=task.output_pydantic
)
else:
agent_output = executor_agent.chat(
task_prompt,
tools=task.tools,
output_json=task.output_json,
output_pydantic=task.output_pydantic
)
if agent_output:
# Store the response in memory
if task.memory:
try:
task.store_in_memory(
content=agent_output,
agent_name=executor_agent.name,
task_id=task_id
)
except Exception as e:
logger.error(f"Failed to store agent output in memory: {e}")
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:
logger.warning(f"Warning: Could not parse output of task {task_id} as JSON")
logger.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:
logger.warning(f"Warning: Could not parse output of task {task_id} as Pydantic Model")
logger.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
task = self.tasks[task_id]
if task.status == "completed":
logger.info(f"Task with ID {task_id} is already completed")
return
retries = 0
while task.status != "completed" and retries < self.max_retries:
logger.debug(f"Attempt {retries+1} for task {task_id}")
if task.status in ["not started", "in progress"]:
task_output = self.execute_task(task_id)
if task_output and self.completion_checker(task, task_output.raw):
task.status = "completed"
# Run execute_callback for memory operations
try:
try:
# If a loop is already running, just create the task
loop = asyncio.get_running_loop()
loop.create_task(task.execute_callback(task_output))
except RuntimeError:
# Otherwise, create and set a new loop, and run the callback
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.create_task(task.execute_callback(task_output))
except Exception as e:
logger.error(f"Error executing memory callback for task {task_id}: {e}")
logger.exception(e)
# Run task callback if exists
if task.callback:
try:
if asyncio.iscoroutinefunction(task.callback):
if asyncio.get_event_loop().is_running():
asyncio.create_task(task.callback(task_output))
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(task.callback(task_output))
else:
task.callback(task_output)
except Exception as e:
logger.error(f"Error executing task callback for task {task_id}: {e}")
logger.exception(e)
self.save_output_to_file(task, task_output)
if self.verbose >= 1:
logger.info(f"Task {task_id} completed successfully.")
else:
task.status = "in progress"
if self.verbose >= 1:
logger.info(f"Task {task_id} not completed, retrying")
time.sleep(1)
retries += 1
else:
if task.status == "failed":
logger.info("Task is failed, resetting to in-progress for another try...")
task.status = "in progress"
else:
logger.info("Invalid Task status")
break
if retries == self.max_retries and task.status != "completed":
logger.info(f"Task {task_id} failed after {self.max_retries} retries.")
def run_all_tasks(self):
"""Synchronous version of run_all_tasks method"""
process = Process(
tasks=self.tasks,
agents=self.agents,
manager_llm=self.manager_llm,
verbose=self.verbose,
max_iter=self.max_iter
)
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":
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:
return self.tasks[task_id].status
return None
def get_all_tasks_status(self):
return {task_id: self.tasks[task_id].status for task_id in self.tasks}
def get_task_result(self, task_id):
if task_id in self.tasks:
return self.tasks[task_id].result
return None
def get_task_details(self, task_id):
if task_id in self.tasks:
return str(self.tasks[task_id])
return None
def get_agent_details(self, agent_name):
agent = [task.agent for task in self.tasks.values() if task.agent and task.agent.name == agent_name]
if agent:
return str(agent[0])
return None
def start(self, content=None, **kwargs):
"""Start agent execution with optional content and config"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
# If context is empty, initialize it
if not task.context:
task.context = []
# Add content to context
task.context.append(content)
# Run tasks as before
self.run_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 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()
-335
View File
@@ -1,335 +0,0 @@
"""
AutoAgents - A class for automatically creating and managing AI agents and tasks.
This class provides a simplified interface for creating and running AI agents with tasks.
It automatically handles agent creation, task setup, and execution flow.
"""
from .agents import PraisonAIAgents
from ..agent.agent import Agent
from ..task.task import Task
from typing import List, Any, Optional, Dict, Union
import logging
import os
from pydantic import BaseModel, Field
from ..main import display_instruction, display_tool_call, display_interaction, client
# Define Pydantic models for structured output
class TaskConfig(BaseModel):
name: str
description: str
expected_output: str
tools: List[str]
class AgentConfig(BaseModel):
name: str
role: str
goal: str
backstory: str
tools: List[str]
tasks: List[TaskConfig]
class AutoAgentsConfig(BaseModel):
main_instruction: str
process_type: str
agents: List[AgentConfig]
class AutoAgents(PraisonAIAgents):
def __init__(
self,
instructions: str,
tools: Optional[List[Any]] = None,
verbose: bool = False,
process: str = "sequential",
manager_llm: Optional[str] = None,
max_retries: int = 5,
completion_checker: Optional[Any] = None,
allow_code_execution: bool = False,
memory: bool = True,
markdown: bool = True,
self_reflect: bool = False,
max_reflect: int = 3,
min_reflect: int = 1,
llm: Optional[str] = None,
function_calling_llm: Optional[str] = None,
respect_context_window: bool = True,
code_execution_mode: str = "safe",
embedder_config: Optional[Dict[str, Any]] = None,
knowledge_sources: Optional[List[Any]] = None,
use_system_prompt: bool = True,
cache: bool = True,
allow_delegation: bool = False,
step_callback: Optional[Any] = None,
system_template: Optional[str] = None,
prompt_template: Optional[str] = None,
response_template: Optional[str] = None,
max_rpm: Optional[int] = None,
max_execution_time: Optional[int] = None,
max_iter: int = 20,
reflect_llm: Optional[str] = None,
base_url: Optional[str] = None,
api_key: Optional[str] = None,
max_agents: int = 3 # New parameter for maximum number of agents
):
"""Initialize AutoAgents with configuration for automatic agent and task creation."""
if max_agents < 1:
raise ValueError("max_agents must be at least 1")
if max_agents > 10:
raise ValueError("max_agents cannot exceed 10")
# Store all configuration parameters first
self.instructions = instructions
self.tools = tools or []
self.verbose = verbose # Store verbose parameter
self.max_agents = max_agents # Store max_agents parameter
self.allow_code_execution = allow_code_execution
self.memory = memory
self.markdown = markdown
self.self_reflect = self_reflect
self.max_reflect = max_reflect
self.min_reflect = min_reflect
self.llm = llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
self.function_calling_llm = function_calling_llm
self.respect_context_window = respect_context_window
self.code_execution_mode = code_execution_mode
self.embedder_config = embedder_config
self.knowledge_sources = knowledge_sources
self.use_system_prompt = use_system_prompt
self.cache = cache
self.allow_delegation = allow_delegation
self.step_callback = step_callback
self.system_template = system_template
self.prompt_template = prompt_template
self.response_template = response_template
self.max_rpm = max_rpm
self.max_execution_time = max_execution_time
self.max_iter = max_iter
self.reflect_llm = reflect_llm
# Display initial instruction
if self.verbose:
display_instruction(f"🎯 Main Task: {self.instructions}")
display_instruction(f"📊 Maximum Agents: {self.max_agents}")
if self.tools:
tool_names = [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools]
display_tool_call(f"🛠️ Available Tools: {', '.join(tool_names)}")
# Generate agents and tasks configuration
config = self._generate_config()
agents, tasks = self._create_agents_and_tasks(config)
# Display agents and their tasks
if self.verbose:
self._display_agents_and_tasks(agents, tasks)
# Initialize parent class with generated agents and tasks
super().__init__(
agents=agents,
tasks=tasks,
verbose=verbose,
completion_checker=completion_checker,
max_retries=max_retries,
process=process,
manager_llm=manager_llm
)
def _display_agents_and_tasks(self, agents: List[Agent], tasks: List[Task]):
"""Display the created agents and their assigned tasks"""
display_instruction("\n🤖 Generated Agents and Tasks:")
# Create a mapping of agents to their tasks
agent_tasks = {}
for task in tasks:
if task.agent not in agent_tasks:
agent_tasks[task.agent] = []
agent_tasks[task.agent].append(task)
# Display each agent and their tasks
for agent in agents:
agent_tools = [t.__name__ if hasattr(t, '__name__') else str(t) for t in agent.tools]
display_interaction(
f"\n👤 Agent: {agent.name}",
f"""Role: {agent.role}
Goal: {agent.goal}
Tools: {', '.join(agent_tools)}"""
)
# Display tasks for this agent
if agent in agent_tasks:
for i, task in enumerate(agent_tasks[agent], 1):
task_tools = [t.__name__ if hasattr(t, '__name__') else str(t) for t in task.tools]
display_instruction(
f""" 📋 Task {i}: {task.name}
Description: {task.description}
Expected Output: {task.expected_output}
Tools: {', '.join(task_tools)}"""
)
def _get_available_tools(self) -> List[str]:
"""Get list of available tools"""
if not self.tools:
return []
return [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools]
def _get_tool_by_name(self, tool_name: str) -> Optional[Any]:
"""Get tool object by its name"""
for tool in self.tools:
if (hasattr(tool, '__name__') and tool.__name__ == tool_name) or str(tool) == tool_name:
return tool
return None
def _assign_tools_to_agent(self, agent_config: AgentConfig) -> List[Any]:
"""
Assign appropriate tools to an agent based on its role and tasks.
Args:
agent_config: The agent configuration containing role and required tools
Returns:
List of tool objects assigned to this agent
"""
assigned_tools = []
tool_names = set(agent_config.tools)
# Also look at task requirements
for task in agent_config.tasks:
tool_names.update(task.tools)
# Assign tools that match the requirements
for tool_name in tool_names:
tool = self._get_tool_by_name(tool_name)
if tool:
assigned_tools.append(tool)
# If no specific tools matched but we have tools available,
# assign all tools to ensure functionality
if not assigned_tools and self.tools:
assigned_tools = self.tools
return assigned_tools
def _generate_config(self) -> AutoAgentsConfig:
"""Generate the configuration for agents and tasks"""
prompt = f"""
Generate a configuration for AI agents to accomplish this task: "{self.instructions}"
The configuration should include:
1. A main instruction that clearly states the overall goal
2. A process type (sequential, workflow, or hierarchical)
3. A list of maximum {self.max_agents} agents (no more, no less), each with:
- Name, role, goal, and backstory
- List of required tools from: {self._get_available_tools()}
- Only add tools that are needed for the agent to perform its task
- Only one task per agent. Add more than one task if absolutely necessary.
- List of specific tasks they need to perform
- Whether they should self-reflect or allow delegation
Requirements:
1. Each agent should have clear, focused responsibilities
2. Tasks should be broken down into manageable steps
3. Tool selection should be appropriate for each task
4. The process type should match the task requirements
5. Generate maximum {self.max_agents} agents to handle this task efficiently
Return the configuration in a structured JSON format matching the AutoAgentsConfig schema.
"""
try:
response = client.beta.chat.completions.parse(
model=self.llm,
response_format=AutoAgentsConfig,
messages=[
{"role": "system", "content": "You are a helpful assistant designed to generate AI agent configurations."},
{"role": "user", "content": prompt}
]
)
# Ensure we have exactly max_agents number of agents
if len(response.choices[0].message.parsed.agents) > self.max_agents:
response.choices[0].message.parsed.agents = response.choices[0].message.parsed.agents[:self.max_agents]
elif len(response.choices[0].message.parsed.agents) < self.max_agents:
logging.warning(f"Generated {len(response.choices[0].message.parsed.agents)} agents, expected {self.max_agents}")
return response.choices[0].message.parsed
except Exception as e:
logging.error(f"Error generating configuration: {e}")
raise
def _create_agents_and_tasks(self, config: AutoAgentsConfig) -> tuple[List[Agent], List[Task]]:
"""Create agents and tasks from configuration"""
agents = []
tasks = []
for agent_config in config.agents:
# Get appropriate tools for this agent
agent_tools = self._assign_tools_to_agent(agent_config)
# Create the agent with all parameters
agent = Agent(
name=agent_config.name,
role=agent_config.role,
goal=agent_config.goal,
backstory=agent_config.backstory,
tools=agent_tools, # Use assigned tools
verbose=self.verbose >= 1,
allow_code_execution=self.allow_code_execution,
memory=self.memory,
markdown=self.markdown,
self_reflect=self.self_reflect,
max_reflect=self.max_reflect,
min_reflect=self.min_reflect,
llm=self.llm,
function_calling_llm=self.function_calling_llm,
respect_context_window=self.respect_context_window,
code_execution_mode=self.code_execution_mode,
embedder_config=self.embedder_config,
knowledge_sources=self.knowledge_sources,
use_system_prompt=self.use_system_prompt,
cache=self.cache,
allow_delegation=self.allow_delegation,
step_callback=self.step_callback,
system_template=self.system_template,
prompt_template=self.prompt_template,
response_template=self.response_template,
max_rpm=self.max_rpm,
max_execution_time=self.max_execution_time,
max_iter=self.max_iter,
reflect_llm=self.reflect_llm
)
agents.append(agent)
# Create tasks for this agent
for task_config in agent_config.tasks:
# Get task-specific tools
task_tools = [self._get_tool_by_name(t) for t in task_config.tools]
task_tools = [t for t in task_tools if t] # Remove None values
# If no specific tools matched, use agent's tools
if not task_tools:
task_tools = agent_tools
task = Task(
name=task_config.name,
description=task_config.description,
expected_output=task_config.expected_output,
agent=agent,
tools=task_tools # Use task-specific tools
)
tasks.append(task)
return agents, tasks
async def astart(self):
"""
Async version of start() method.
Creates tasks based on the instructions, then starts execution.
Returns the task status and results dictionary.
"""
return await super().astart()
def start(self):
"""
Creates tasks based on the instructions, then starts execution.
Returns the task status and results dictionary.
"""
return super().start()
@@ -1,8 +0,0 @@
"""
PraisonAI Knowledge - Advanced knowledge management system with configurable features
"""
from praisonaiagents.knowledge.knowledge import Knowledge
from praisonaiagents.knowledge.chunking import Chunking
__all__ = ["Knowledge", "Chunking"]
@@ -1,182 +0,0 @@
from typing import List, Union, Optional, Dict, Any
from functools import cached_property
import importlib
class Chunking:
"""A unified class for text chunking with various chunking strategies."""
CHUNKER_PARAMS = {
'token': ['chunk_size', 'chunk_overlap', 'tokenizer'],
'word': ['chunk_size', 'chunk_overlap', 'tokenizer'],
'sentence': ['chunk_size', 'chunk_overlap', 'tokenizer'],
'semantic': ['chunk_size', 'embedding_model', 'tokenizer'],
'sdpm': ['chunk_size', 'embedding_model', 'tokenizer'],
'late': ['chunk_size', 'embedding_model', 'tokenizer'],
'recursive': ['chunk_size', 'tokenizer']
}
@cached_property
def SUPPORTED_CHUNKERS(self) -> Dict[str, Any]:
"""Lazy load chunker classes."""
try:
from chonkie.chunker import (
TokenChunker,
WordChunker,
SentenceChunker,
SemanticChunker,
SDPMChunker,
LateChunker,
RecursiveChunker
)
except ImportError:
raise ImportError(
"chonkie package not found. Please install it using: pip install 'praisonaiagents[knowledge]'"
)
return {
'token': TokenChunker,
'word': WordChunker,
'sentence': SentenceChunker,
'semantic': SemanticChunker,
'sdpm': SDPMChunker,
'late': LateChunker,
'recursive': RecursiveChunker
}
def __init__(
self,
chunker_type: str = 'token',
chunk_size: int = 512,
chunk_overlap: int = 128,
tokenizer: str = "gpt2",
embedding_model: Optional[Union[str, Any]] = None,
**kwargs
):
"""Initialize the Chunking class."""
if chunker_type not in self.CHUNKER_PARAMS:
raise ValueError(
f"Unsupported chunker type: {chunker_type}. "
f"Must be one of: {list(self.CHUNKER_PARAMS.keys())}"
)
self.chunker_type = chunker_type
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
self.tokenizer = tokenizer
self._embedding_model = embedding_model
self.kwargs = kwargs
# Initialize these as None for lazy loading
self._chunker = None
self._embeddings = None
@cached_property
def embedding_model(self):
"""Lazy load the embedding model."""
if self._embedding_model is None and self.chunker_type in ['semantic', 'sdpm', 'late']:
from chonkie.embeddings import AutoEmbeddings
return AutoEmbeddings.get_embeddings("all-MiniLM-L6-v2")
elif isinstance(self._embedding_model, str):
from chonkie.embeddings import AutoEmbeddings
return AutoEmbeddings.get_embeddings(self._embedding_model)
return self._embedding_model
def _get_chunker_params(self) -> Dict[str, Any]:
"""Get the appropriate parameters for the current chunker type."""
allowed_params = self.CHUNKER_PARAMS[self.chunker_type]
params = {'chunk_size': self.chunk_size}
if 'chunk_overlap' in allowed_params:
params['chunk_overlap'] = self.chunk_overlap
if 'tokenizer' in allowed_params:
if self.chunker_type in ['semantic', 'sdpm', 'late']:
params['tokenizer'] = self.embedding_model.get_tokenizer_or_token_counter()
else:
params['tokenizer'] = self.tokenizer
if 'embedding_model' in allowed_params:
params['embedding_model'] = self.embedding_model
# Add any additional kwargs that are in allowed_params
for key, value in self.kwargs.items():
if key in allowed_params:
params[key] = value
return params
@cached_property
def chunker(self):
"""Lazy load the chunker instance."""
if self._chunker is None:
chunker_cls = self.SUPPORTED_CHUNKERS[self.chunker_type]
common_params = self._get_chunker_params()
self._chunker = chunker_cls(**common_params)
return self._chunker
def _get_overlap_refinery(self, context_size: Optional[int] = None, **kwargs):
"""Lazy load the overlap refinery."""
try:
from chonkie.refinery import OverlapRefinery
except ImportError:
raise ImportError("Failed to import OverlapRefinery from chonkie.refinery")
if context_size is None:
context_size = self.chunk_overlap
return OverlapRefinery(
context_size=context_size,
tokenizer=self.chunker.tokenizer,
**kwargs
)
def add_overlap_context(
self,
chunks: List[Any],
context_size: int = None,
mode: str = "suffix",
merge_context: bool = True
) -> List[Any]:
"""Add overlap context to chunks using OverlapRefinery."""
refinery = self._get_overlap_refinery(
context_size=context_size,
mode=mode,
merge_context=merge_context
)
return refinery.refine(chunks)
def chunk(
self,
text: Union[str, List[str]],
add_context: bool = False,
context_params: Optional[Dict[str, Any]] = None
) -> Union[List[Any], List[List[Any]]]:
"""Chunk text using the configured chunking strategy."""
chunks = self.chunker(text)
if add_context:
context_params = context_params or {}
if isinstance(text, str):
chunks = self.add_overlap_context(chunks, **context_params)
else:
chunks = [self.add_overlap_context(c, **context_params) for c in chunks]
return chunks
def __call__(
self,
text: Union[str, List[str]],
add_context: bool = False,
context_params: Optional[Dict[str, Any]] = None
) -> Union[List[Any], List[List[Any]]]:
"""Make the Chunking instance callable."""
return self.chunk(text, add_context, context_params)
def __repr__(self) -> str:
"""String representation of the Chunking instance."""
return (
f"Chunking(chunker_type='{self.chunker_type}', "
f"chunk_size={self.chunk_size}, "
f"chunk_overlap={self.chunk_overlap})"
)
@@ -1,321 +0,0 @@
import os
import logging
import uuid
import time
from .chunking import Chunking
from functools import cached_property
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn
logger = logging.getLogger(__name__)
class CustomMemory:
@classmethod
def from_config(cls, config):
from mem0 import Memory
return type('CustomMemory', (Memory,), {
'_add_to_vector_store': cls._add_to_vector_store
}).from_config(config)
@staticmethod
def _add_to_vector_store(self, messages, metadata, filters):
# Custom implementation that doesn't use LLM
parsed_messages = "\n".join([msg["content"] for msg in messages])
# Create a simple fact without using LLM
new_retrieved_facts = [parsed_messages]
# Process embeddings and continue with vector store operations
new_message_embeddings = {}
for new_mem in new_retrieved_facts:
messages_embeddings = self.embedding_model.embed(new_mem)
new_message_embeddings[new_mem] = messages_embeddings
# Create the memory
memory_id = self._create_memory(
data=parsed_messages,
existing_embeddings=new_message_embeddings,
metadata=metadata
)
return [{
"id": memory_id,
"memory": parsed_messages,
"event": "ADD"
}]
class Knowledge:
def __init__(self, config=None, verbose=None):
self._config = config
self._verbose = verbose or 0
os.environ['ANONYMIZED_TELEMETRY'] = 'False' # Chromadb
# Configure logging levels based on verbose setting
if not self._verbose:
# Suppress logs from all relevant dependencies
for logger_name in [
'mem0',
'chromadb',
'local_persistent_hnsw',
'_client',
'main'
]:
logging.getLogger(logger_name).setLevel(logging.WARNING)
# Disable OpenAI API request logging
logging.getLogger('openai').setLevel(logging.WARNING)
# Set root logger to warning to catch any uncategorized logs
logging.getLogger().setLevel(logging.WARNING)
@cached_property
def _deps(self):
try:
from markitdown import MarkItDown
import chromadb
return {
'chromadb': chromadb,
'markdown': MarkItDown()
}
except ImportError:
raise ImportError(
"Required packages not installed. Please install using: "
'pip install "praisonaiagents[knowledge]"'
)
@cached_property
def config(self):
# Generate unique collection name for each instance (only if not provided in config)
default_collection = f"test_{int(time.time())}_{str(uuid.uuid4())[:8]}"
persist_dir = ".praison"
# Create persistent client config
base_config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": default_collection,
"path": persist_dir,
"client": self._deps['chromadb'].PersistentClient(path=persist_dir),
"host": None,
"port": None
}
},
"version": "v1.1",
"custom_prompt": "Return {{\"facts\": [text]}} where text is the exact input provided and json response"
}
# If config is provided, merge it with base config
if self._config:
# Merge version if provided
if "version" in self._config:
base_config["version"] = self._config["version"]
# Merge vector_store config
if "vector_store" in self._config:
if "provider" in self._config["vector_store"]:
base_config["vector_store"]["provider"] = self._config["vector_store"]["provider"]
if "config" in self._config["vector_store"]:
config_copy = self._config["vector_store"]["config"].copy()
# Only exclude client as it's managed internally
if "client" in config_copy:
del config_copy["client"]
base_config["vector_store"]["config"].update(config_copy)
# Merge embedder config if provided
if "embedder" in self._config:
base_config["embedder"] = self._config["embedder"]
# Merge llm config if provided
if "llm" in self._config:
base_config["llm"] = self._config["llm"]
return base_config
@cached_property
def memory(self):
try:
return CustomMemory.from_config(self.config)
except (NotImplementedError, ValueError) as e:
if "list_collections" in str(e) or "Extra fields not allowed" in str(e):
# Keep only allowed fields
vector_store_config = {
"collection_name": self.config["vector_store"]["config"]["collection_name"],
"path": self.config["vector_store"]["config"]["path"]
}
self.config["vector_store"]["config"] = vector_store_config
from mem0 import Memory
return Memory.from_config(self.config)
raise
@cached_property
def markdown(self):
return self._deps['markdown']
@cached_property
def chunker(self):
return Chunking(
chunker_type='recursive',
chunk_size=512,
chunk_overlap=50
)
def _log(self, message, level=2):
"""Internal logging helper"""
if self._verbose and self._verbose >= level:
logger.info(message)
def store(self, content, user_id=None, agent_id=None, run_id=None, metadata=None):
"""Store a memory."""
try:
if isinstance(content, str):
if any(content.lower().endswith(ext) for ext in ['.pdf', '.doc', '.docx', '.txt']):
self._log(f"Content appears to be a file path, processing file: {content}")
return self.add(content, user_id=user_id, agent_id=agent_id, run_id=run_id, metadata=metadata)
content = content.strip()
if not content:
return []
result = self.memory.add(content, user_id=user_id, agent_id=agent_id, run_id=run_id, metadata=metadata)
self._log(f"Store operation result: {result}")
return result
except Exception as e:
logger.error(f"Error storing content: {str(e)}")
return []
def get_all(self, user_id=None, agent_id=None, run_id=None):
"""Retrieve all memories."""
return self.memory.get_all(user_id=user_id, agent_id=agent_id, run_id=run_id)
def get(self, memory_id):
"""Retrieve a specific memory by ID."""
return self.memory.get(memory_id)
def search(self, query, user_id=None, agent_id=None, run_id=None):
"""Search for memories related to a query."""
return self.memory.search(query, user_id=user_id, agent_id=agent_id, run_id=run_id)
def update(self, memory_id, data):
"""Update a memory."""
return self.memory.update(memory_id, data)
def history(self, memory_id):
"""Get the history of changes for a memory."""
return self.memory.history(memory_id)
def delete(self, memory_id):
"""Delete a memory."""
self.memory.delete(memory_id)
def delete_all(self, user_id=None, agent_id=None, run_id=None):
"""Delete all memories."""
self.memory.delete_all(user_id=user_id, agent_id=agent_id, run_id=run_id)
def reset(self):
"""Reset all memories."""
self.memory.reset()
def normalize_content(self, content):
"""Normalize content for consistent storage."""
# Example normalization: strip whitespace, convert to lowercase
return content.strip().lower()
def add(self, file_path, user_id=None, agent_id=None, run_id=None, metadata=None):
"""Read file content and store it in memory.
Args:
file_path: Can be:
- A string path to local file
- A URL string
- A list containing file paths and/or URLs
"""
if isinstance(file_path, (list, tuple)):
results = []
for path in file_path:
result = self._process_single_input(path, user_id, agent_id, run_id, metadata)
results.extend(result.get('results', []))
return {'results': results, 'relations': []}
return self._process_single_input(file_path, user_id, agent_id, run_id, metadata)
def _process_single_input(self, input_path, user_id=None, agent_id=None, run_id=None, metadata=None):
"""Process a single input which can be a file path or URL."""
try:
# Define supported file extensions
DOCUMENT_EXTENSIONS = {
'document': ('.pdf', '.ppt', '.pptx', '.doc', '.docx', '.xls', '.xlsx'),
'media': ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.mp3', '.wav', '.ogg', '.m4a'),
'text': ('.txt', '.csv', '.json', '.xml', '.md', '.html', '.htm'),
'archive': '.zip'
}
# Check if input is URL
if isinstance(input_path, str) and (input_path.startswith('http://') or input_path.startswith('https://')):
self._log(f"Processing URL: {input_path}")
raise NotImplementedError("URL processing not yet implemented")
# Check if input ends with any supported extension
is_supported_file = any(input_path.lower().endswith(ext)
for exts in DOCUMENT_EXTENSIONS.values()
for ext in (exts if isinstance(exts, tuple) else (exts,)))
if is_supported_file:
self._log(f"Processing as file path: {input_path}")
if not os.path.exists(input_path):
logger.error(f"File not found: {input_path}")
raise FileNotFoundError(f"File not found: {input_path}")
file_ext = '.' + input_path.lower().split('.')[-1] # Get extension reliably
# Process file based on type
if file_ext in DOCUMENT_EXTENSIONS['text']:
with open(input_path, 'r', encoding='utf-8') as file:
content = file.read().strip()
if not content:
raise ValueError("Empty text file")
memories = [self.normalize_content(content)]
else:
# Use MarkItDown for documents and media
result = self.markdown.convert(input_path)
content = result.text_content
if not content:
raise ValueError("No content could be extracted from file")
chunks = self.chunker.chunk(content)
memories = [chunk.text.strip() if hasattr(chunk, 'text') else str(chunk).strip()
for chunk in chunks if chunk]
# Set metadata for file
if not metadata:
metadata = {}
metadata['file_type'] = file_ext.lstrip('.')
metadata['filename'] = os.path.basename(input_path)
else:
# Treat as raw text content only if no file extension
memories = [self.normalize_content(input_path)]
# Create progress display
progress = Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TaskProgressColumn(),
transient=True
)
# Store memories with progress bar
all_results = []
with progress:
store_task = progress.add_task(f"Adding to Knowledge from {os.path.basename(input_path)}", total=len(memories))
for memory in memories:
if memory:
memory_result = self.store(memory, user_id=user_id, agent_id=agent_id,
run_id=run_id, metadata=metadata)
if memory_result:
all_results.extend(memory_result.get('results', []))
progress.advance(store_task)
return {'results': all_results, 'relations': []}
except Exception as e:
logger.error(f"Error processing input {input_path}: {str(e)}", exc_info=True)
raise
-20
View File
@@ -1,20 +0,0 @@
import logging
import warnings
# Suppress all relevant logs at module level
logging.getLogger("litellm").setLevel(logging.ERROR)
logging.getLogger("openai").setLevel(logging.ERROR)
logging.getLogger("httpx").setLevel(logging.ERROR)
logging.getLogger("httpcore").setLevel(logging.ERROR)
logging.getLogger("pydantic").setLevel(logging.ERROR)
# Suppress pydantic warnings
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
# Configure logging to suppress all INFO messages
logging.basicConfig(level=logging.WARNING)
# Import after suppressing warnings
from .llm import LLM, LLMContextLengthExceededException
__all__ = ["LLM", "LLMContextLengthExceededException"]
Loaded 100 of 660 files, more files were not shown because too many files have changed in this diff. Show more