mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-09 17:31:52 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bf5a08246 |
No files matched your search
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.3.34" \
|
||||
"praisonai>=2.3.35" \
|
||||
"praisonai[chat]" \
|
||||
"embedchain[github,youtube]"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.3.34" \
|
||||
"praisonai>=2.3.35" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[chat]" \
|
||||
"praisonai[realtime]" \
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.3.34" \
|
||||
"praisonai>=2.3.35" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ Tests single agent running a simple task across frameworks.
|
||||
Usage:
|
||||
export OPENAI_API_KEY=your_key
|
||||
python benchmarks/execution_benchmark.py
|
||||
python benchmarks/execution_benchmark.py --no-save
|
||||
"""
|
||||
|
||||
import time
|
||||
import os
|
||||
import argparse
|
||||
from importlib.metadata import version as get_version
|
||||
|
||||
# Check API key
|
||||
@@ -220,6 +222,10 @@ def save_results(results: dict):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='PraisonAI Agents - Real Execution Benchmark')
|
||||
parser.add_argument('--no-save', action='store_true', help='Do not save results to file')
|
||||
args = parser.parse_args()
|
||||
|
||||
print('=' * 60)
|
||||
print('PraisonAI Agents - Real Execution Benchmark')
|
||||
print('=' * 60)
|
||||
@@ -228,7 +234,7 @@ if __name__ == '__main__':
|
||||
print(f'Prompt: "{PROMPT}"')
|
||||
|
||||
versions = get_package_versions()
|
||||
print(f'\nPackage versions:')
|
||||
print('\nPackage versions:')
|
||||
for pkg, ver in versions.items():
|
||||
print(f' {pkg}: {ver}')
|
||||
|
||||
@@ -273,6 +279,8 @@ if __name__ == '__main__':
|
||||
|
||||
print('\n' + '=' * 60)
|
||||
|
||||
# Save results
|
||||
if results:
|
||||
# Save results (unless --no-save)
|
||||
if results and not args.no_save:
|
||||
save_results(results)
|
||||
elif args.no_save:
|
||||
print('\nResults not saved (--no-save flag used)')
|
||||
@@ -33,7 +33,7 @@
|
||||
"url": "http://127.0.0.1:8005/agents/researcher",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={{ JSON.stringify({ query: $json.body?.query || $json.query || 'Research about Mars environment and cat behavior for the movie concept' } }) }}",
|
||||
"jsonBody": "={{ JSON.stringify({ query: $json.body?.query || $json.query || 'Research about Mars environment and cat behavior for the movie concept' }) }}",
|
||||
"options": {
|
||||
"timeout": 300000
|
||||
}
|
||||
@@ -54,7 +54,7 @@
|
||||
"url": "http://127.0.0.1:8005/agents/narrative_designer",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={{ JSON.stringify({ query: $json.response || 'Create story concept based on research: {{previous_output}}' } }) }}",
|
||||
"jsonBody": "={{ JSON.stringify({ query: $json.response || 'Create story concept based on research: previous_output' }) }}",
|
||||
"options": {
|
||||
"timeout": 300000
|
||||
}
|
||||
@@ -75,7 +75,7 @@
|
||||
"url": "http://127.0.0.1:8005/agents/scriptwriter",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={{ JSON.stringify({ query: $json.response || 'Write the final movie script based on the story concept: {{previous_output}}' } }) }}",
|
||||
"jsonBody": "={{ JSON.stringify({ query: $json.response || 'Write the final movie script based on the story concept: previous_output' }) }}",
|
||||
"options": {
|
||||
"timeout": 300000
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# Advanced Workflow Example
|
||||
# Demonstrates: conditional routing, decision tasks, and multi-agent coordination
|
||||
|
||||
name: Content Creation Pipeline
|
||||
description: A workflow that researches, writes, reviews, and publishes content
|
||||
|
||||
workflow:
|
||||
process: workflow # Use workflow process for conditional execution
|
||||
verbose: true
|
||||
|
||||
agents:
|
||||
researcher:
|
||||
name: Researcher
|
||||
role: Research Specialist
|
||||
goal: Gather comprehensive information on topics
|
||||
backstory: Expert at finding and synthesizing information from various sources
|
||||
instructions: |
|
||||
Research the given topic thoroughly.
|
||||
Provide detailed findings with key points.
|
||||
llm: gpt-4o-mini
|
||||
|
||||
writer:
|
||||
name: Writer
|
||||
role: Content Writer
|
||||
goal: Create engaging and informative content
|
||||
backstory: Skilled writer who transforms research into readable content
|
||||
instructions: |
|
||||
Write clear, engaging content based on the research.
|
||||
Structure the content with introduction, body, and conclusion.
|
||||
llm: gpt-4o-mini
|
||||
|
||||
reviewer:
|
||||
name: Reviewer
|
||||
role: Quality Reviewer
|
||||
goal: Ensure content meets quality standards
|
||||
backstory: Meticulous editor who ensures accuracy and clarity
|
||||
instructions: |
|
||||
Review the content for accuracy, clarity, and engagement.
|
||||
Decide if it's ready for publication or needs revision.
|
||||
llm: gpt-4o-mini
|
||||
|
||||
publisher:
|
||||
name: Publisher
|
||||
role: Content Publisher
|
||||
goal: Finalize and format content for publication
|
||||
backstory: Expert at preparing content for various platforms
|
||||
instructions: |
|
||||
Format the approved content for publication.
|
||||
Add metadata and prepare final deliverable.
|
||||
llm: gpt-4o-mini
|
||||
|
||||
steps:
|
||||
# Step 1: Research (starting point)
|
||||
- name: research_task
|
||||
agent: researcher
|
||||
action: "Research the topic: AI trends in 2025"
|
||||
expected_output: "Comprehensive research findings with key points and sources"
|
||||
is_start: true
|
||||
next_tasks: [write_task]
|
||||
|
||||
# Step 2: Write content based on research
|
||||
- name: write_task
|
||||
agent: writer
|
||||
action: "Write an article based on the research findings"
|
||||
expected_output: "Well-structured article with introduction, body, and conclusion"
|
||||
context: [research_task]
|
||||
next_tasks: [review_task]
|
||||
|
||||
# Step 3: Review with decision (conditional routing)
|
||||
- name: review_task
|
||||
agent: reviewer
|
||||
action: "Review the article for quality and accuracy"
|
||||
expected_output: "Quality assessment with approval or revision recommendation"
|
||||
context: [write_task]
|
||||
task_type: decision
|
||||
condition:
|
||||
approved: [publish_task]
|
||||
needs_revision: [revise_task]
|
||||
|
||||
# Step 4a: Revision (conditional - only if review fails)
|
||||
- name: revise_task
|
||||
agent: writer
|
||||
action: "Revise the article based on reviewer feedback"
|
||||
expected_output: "Revised article addressing all feedback"
|
||||
context: [write_task, review_task]
|
||||
next_tasks: [review_task] # Loop back to review
|
||||
|
||||
# Step 4b: Publish (conditional - only if review passes)
|
||||
- name: publish_task
|
||||
agent: publisher
|
||||
action: "Prepare the approved article for publication"
|
||||
expected_output: "Final formatted article ready for publication"
|
||||
context: [write_task, review_task]
|
||||
@@ -3,8 +3,8 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.34.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.34.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.35.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.35.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -412,12 +412,14 @@ class N8nHandler(FlagHandler):
|
||||
agent_url_id = agent_id.lower().replace(' ', '_')
|
||||
|
||||
# Build the query - first agent uses webhook input, others use previous response
|
||||
# Escape single quotes and double braces (n8n expression syntax)
|
||||
escaped_action = action.replace("'", "\\'").replace("{{", "").replace("}}", "")
|
||||
if is_first:
|
||||
# First agent: use query from webhook body
|
||||
query_expr = f"={{ $json.body?.query || $json.query || '{action}' }}"
|
||||
query_expr = "$json.body?.query || $json.query || '" + escaped_action + "'"
|
||||
else:
|
||||
# Subsequent agents: use previous agent's response + original action context
|
||||
query_expr = f"={{ $json.response || '{action}' }}"
|
||||
query_expr = "$json.response || '" + escaped_action + "'"
|
||||
|
||||
return {
|
||||
"id": f"agent_{index}",
|
||||
@@ -430,7 +432,7 @@ class N8nHandler(FlagHandler):
|
||||
"url": f"{self.praisonai_api_url}/agents/{agent_url_id}",
|
||||
"sendBody": True,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": f"={{{{ JSON.stringify({{ query: {query_expr[2:]} }}) }}}}",
|
||||
"jsonBody": f"={{{{ JSON.stringify({{ query: {query_expr} }}) }}}}",
|
||||
"options": {
|
||||
"timeout": 300000 # 5 minute timeout per agent
|
||||
}
|
||||
|
||||
@@ -3060,6 +3060,11 @@ Now, {final_instruction.lower()}:"""
|
||||
"""
|
||||
Handle the serve command - start API server for agents.
|
||||
|
||||
Supports:
|
||||
- Sequential workflows with agents and steps
|
||||
- Workflow patterns: route, parallel, loop, repeat
|
||||
- All process types: sequential, workflow, hierarchical
|
||||
|
||||
Usage:
|
||||
praisonai serve agents.yaml
|
||||
praisonai serve agents.yaml --port 8005 --host 0.0.0.0
|
||||
@@ -3090,7 +3095,7 @@ Now, {final_instruction.lower()}:"""
|
||||
print(" praisonai agents.yaml --serve")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"📄 Loading agents from: {yaml_file}")
|
||||
print(f"📄 Loading workflow from: {yaml_file}")
|
||||
|
||||
# Load YAML file
|
||||
with open(yaml_file, 'r') as f:
|
||||
@@ -3124,6 +3129,20 @@ Now, {final_instruction.lower()}:"""
|
||||
steps = config.get('steps', [])
|
||||
tasks_list = []
|
||||
|
||||
# Detect advanced workflow patterns
|
||||
has_route = any(isinstance(s, dict) and 'route' in s for s in steps)
|
||||
has_parallel = any(isinstance(s, dict) and 'parallel' in s for s in steps)
|
||||
has_loop = any(isinstance(s, dict) and 'loop' in s for s in steps)
|
||||
has_repeat = any(isinstance(s, dict) and 'repeat' in s for s in steps)
|
||||
|
||||
if has_route or has_parallel or has_loop or has_repeat:
|
||||
patterns = []
|
||||
if has_route: patterns.append("route")
|
||||
if has_parallel: patterns.append("parallel")
|
||||
if has_loop: patterns.append("loop")
|
||||
if has_repeat: patterns.append("repeat")
|
||||
print(f"\n🔀 Detected workflow patterns: {', '.join(patterns)}")
|
||||
|
||||
if steps:
|
||||
from praisonaiagents import Task
|
||||
print(f"\n📋 Loading workflow steps...")
|
||||
@@ -3132,6 +3151,38 @@ Now, {final_instruction.lower()}:"""
|
||||
task_name_map = {} # Map step names to Task objects for context/next_tasks
|
||||
for i, step in enumerate(steps):
|
||||
if isinstance(step, dict):
|
||||
# Handle advanced patterns
|
||||
if 'route' in step:
|
||||
print(f" ✓ Loaded routing step: {step.get('name', f'route_{i+1}')}")
|
||||
continue # Route steps are handled by workflow process
|
||||
if 'parallel' in step:
|
||||
parallel_tasks = step.get('parallel', [])
|
||||
print(f" ✓ Loaded parallel step: {len(parallel_tasks)} concurrent tasks")
|
||||
for j, pt in enumerate(parallel_tasks):
|
||||
if isinstance(pt, dict):
|
||||
agent_id = pt.get('agent', '')
|
||||
action = pt.get('action', pt.get('description', ''))
|
||||
if agent_id in agents_dict:
|
||||
task = Task(
|
||||
name=f"parallel_{i}_{j}",
|
||||
description=action,
|
||||
agent=agents_dict[agent_id],
|
||||
expected_output=pt.get('expected_output', 'Completed task output'),
|
||||
async_execution=True, # Parallel tasks run async
|
||||
)
|
||||
tasks_list.append(task)
|
||||
task_name_map[f"parallel_{i}_{j}"] = task
|
||||
continue
|
||||
if 'loop' in step:
|
||||
loop_config = step.get('loop', {})
|
||||
print(f" ✓ Loaded loop step: over '{loop_config.get('over', 'items')}'")
|
||||
continue # Loop steps are handled by workflow process
|
||||
if 'repeat' in step:
|
||||
repeat_config = step.get('repeat', {})
|
||||
print(f" ✓ Loaded repeat step: until '{repeat_config.get('until', 'done')}'")
|
||||
continue # Repeat steps are handled by workflow process
|
||||
|
||||
# Standard step
|
||||
agent_id = step.get('agent', '')
|
||||
action = step.get('action', step.get('description', ''))
|
||||
task_name = step.get('name', f"step_{i+1}")
|
||||
@@ -3153,7 +3204,7 @@ Now, {final_instruction.lower()}:"""
|
||||
|
||||
# Second pass: set up next_tasks and context relationships
|
||||
for i, step in enumerate(steps):
|
||||
if isinstance(step, dict):
|
||||
if isinstance(step, dict) and 'agent' in step:
|
||||
task_name = step.get('name', f"step_{i+1}")
|
||||
if task_name in task_name_map:
|
||||
task = task_name_map[task_name]
|
||||
|
||||
@@ -57,7 +57,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.3.34 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.3.35 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "2.3.34"
|
||||
__version__ = "2.3.35"
|
||||
Reference in new issue
Block a user