diff --git a/Dockerfile b/Dockerfile index 50bc20c..534c3c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.11-slim WORKDIR /app COPY . . -RUN pip install flask praisonai==2.0.41 gunicorn markdown +RUN pip install flask praisonai==2.0.42 gunicorn markdown EXPOSE 8080 CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"] diff --git a/agents/praisonaiagents/process/process.py b/agents/praisonaiagents/process/process.py index 4a441ca..43201f0 100644 --- a/agents/praisonaiagents/process/process.py +++ b/agents/praisonaiagents/process/process.py @@ -130,22 +130,28 @@ async def aworkflow(self) -> AsyncGenerator[str, None]: # Determine next task based on result next_task = None - if current_task.result: + if current_task and current_task.result: if current_task.task_type in ["decision", "loop"]: result = current_task.result.raw.lower() # Check conditions for condition, tasks in current_task.condition.items(): - if condition.lower() in result and tasks: - next_task_name = tasks[0] + if condition.lower() in result: + # Handle both list and direct string values + task_value = tasks[0] if isinstance(tasks, list) else tasks + if not task_value or task_value == "exit": # If empty or explicit exit + logging.info("Workflow exit condition met, ending workflow") + current_task = None + break + next_task_name = task_value next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None) # For loops, allow revisiting the same task if next_task and next_task.id == current_task.id: visited_tasks.discard(current_task.id) break - if not next_task and current_task.next_tasks: - next_task_name = current_task.next_tasks[0] - next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None) + if not next_task and current_task and current_task.next_tasks: + next_task_name = current_task.next_tasks[0] + next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None) current_task = next_task if not current_task: @@ -391,22 +397,28 @@ def workflow(self): # Determine next task based on result next_task = None - if current_task.result: + if current_task and current_task.result: if current_task.task_type in ["decision", "loop"]: result = current_task.result.raw.lower() # Check conditions for condition, tasks in current_task.condition.items(): - if condition.lower() in result and tasks: - next_task_name = tasks[0] + if condition.lower() in result: + # Handle both list and direct string values + task_value = tasks[0] if isinstance(tasks, list) else tasks + if not task_value or task_value == "exit": # If empty or explicit exit + logging.info("Workflow exit condition met, ending workflow") + current_task = None + break + next_task_name = task_value next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None) # For loops, allow revisiting the same task if next_task and next_task.id == current_task.id: visited_tasks.discard(current_task.id) break - if not next_task and current_task.next_tasks: - next_task_name = current_task.next_tasks[0] - next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None) + if not next_task and current_task and current_task.next_tasks: + next_task_name = current_task.next_tasks[0] + next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None) current_task = next_task if not current_task: diff --git a/agents/prompt_chaining.py b/agents/prompt_chaining.py index 185ee30..31f96cb 100644 --- a/agents/prompt_chaining.py +++ b/agents/prompt_chaining.py @@ -10,82 +10,72 @@ def get_time_check(): print(f"Time check: {current_time} is {result}") return result -def create_prompt_chain(): - # Create agents for each step in the chain - agent1 = Agent( - name="Time Checker", - role="Time checker", - goal="Check if the time is even or odd", - instructions="Check if the time is even or odd", - tools=[get_time_check] - ) +# Create agents for each step in the chain +agent1 = Agent( + name="Time Checker", + role="Time checker", + goal="Check if the time is even or odd", + instructions="Check if the time is even or odd", + tools=[get_time_check] +) - agent2 = Agent( - name="Advanced Analyzer", - role="Advanced data analyzer", - goal="Perform in-depth analysis of processed data", - instructions="Analyze the processed data in detail" - ) +agent2 = Agent( + name="Advanced Analyzer", + role="Advanced data analyzer", + goal="Perform in-depth analysis of processed data", + instructions="Analyze the processed data in detail" +) - agent3 = Agent( - name="Final Processor", - role="Final data processor", - goal="Generate final output based on analysis", - instructions="Create final output based on analyzed data" - ) +agent3 = Agent( + name="Final Processor", + role="Final data processor", + goal="Generate final output based on analysis", + instructions="Create final output based on analyzed data" +) - # Create tasks for each step - initial_task = Task( - name="time_check", - description="Getting time check and checking if it is even or odd", - expected_output="Getting time check and checking if it is even or odd", - agent=agent1, - is_start=True, # Mark as the starting task - task_type="decision", # This task will make a decision - next_tasks=["advanced_analysis"], # Next task if condition passes - condition={ - "even": ["advanced_analysis"], # If passes, go to advanced analysis - "odd": ["final_processing"] # If fails, exit the chain - } - ) +# Create tasks for each step +initial_task = Task( + name="time_check", + description="Getting time check and checking if it is even or odd", + expected_output="Getting time check and checking if it is even or odd", + agent=agent1, + is_start=True, # Mark as the starting task + task_type="decision", # This task will make a decision + next_tasks=["advanced_analysis"], # Next task if condition passes + condition={ + "even": ["advanced_analysis"], # If passes, go to advanced analysis + "odd": "" # If fails, exit the chain + } +) - analysis_task = Task( - name="advanced_analysis", - description="Perform advanced analysis on the processed data", - expected_output="Analyzed data ready for final processing", - agent=agent2, - next_tasks=["final_processing"] - ) +analysis_task = Task( + name="advanced_analysis", + description="Perform advanced analysis on the processed data", + expected_output="Analyzed data ready for final processing", + agent=agent2, + next_tasks=["final_processing"] +) - final_task = Task( - name="final_processing", - description="Generate final output", - expected_output="Final processed result", - agent=agent3 - ) +final_task = Task( + name="final_processing", + description="Generate final output", + expected_output="Final processed result", + agent=agent3 +) - # Create the workflow manager - workflow = PraisonAIAgents( - agents=[agent1, agent2, agent3], - tasks=[initial_task, analysis_task, final_task], - process="workflow", # Use workflow process type - verbose=True - ) +# Create the workflow manager +workflow = PraisonAIAgents( + agents=[agent1, agent2, agent3], + tasks=[initial_task, analysis_task, final_task], + process="workflow", # Use workflow process type + verbose=True +) - return workflow +# Run the workflow +results = workflow.start() -def main(): - # Create and run the prompt chain - workflow = create_prompt_chain() - - # Run the workflow - results = workflow.start() - - # Print results - print("\nWorkflow Results:") - for task_id, result in results["task_results"].items(): - if result: - print(f"Task {task_id}: {result.raw}") - -if __name__ == "__main__": - main() +# Print results +print("\nWorkflow Results:") +for task_id, result in results["task_results"].items(): + if result: + print(f"Task {task_id}: {result.raw}") diff --git a/agents/pyproject.toml b/agents/pyproject.toml index a336d8b..ac5b131 100644 --- a/agents/pyproject.toml +++ b/agents/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "praisonaiagents" -version = "0.0.31" +version = "0.0.32" description = "Praison AI agents for completing complex tasks with Self Reflection Agents" authors = [ { name="Mervin Praison" } diff --git a/agents/uv.lock b/agents/uv.lock index 4215730..eedf77e 100644 --- a/agents/uv.lock +++ b/agents/uv.lock @@ -990,7 +990,7 @@ wheels = [ [[package]] name = "praisonaiagents" -version = "0.0.31" +version = "0.0.32" source = { editable = "." } dependencies = [ { name = "openai" }, diff --git a/cookbooks/general/prompt_chaining.py b/cookbooks/general/prompt_chaining.py new file mode 100644 index 0000000..31f96cb --- /dev/null +++ b/cookbooks/general/prompt_chaining.py @@ -0,0 +1,81 @@ +from praisonaiagents.agent import Agent +from praisonaiagents.task import Task +from praisonaiagents.agents import PraisonAIAgents +from typing import List, Dict +import time + +def get_time_check(): + current_time = int(time.time()) + result = "even" if current_time % 2 == 0 else "odd" + print(f"Time check: {current_time} is {result}") + return result + +# Create agents for each step in the chain +agent1 = Agent( + name="Time Checker", + role="Time checker", + goal="Check if the time is even or odd", + instructions="Check if the time is even or odd", + tools=[get_time_check] +) + +agent2 = Agent( + name="Advanced Analyzer", + role="Advanced data analyzer", + goal="Perform in-depth analysis of processed data", + instructions="Analyze the processed data in detail" +) + +agent3 = Agent( + name="Final Processor", + role="Final data processor", + goal="Generate final output based on analysis", + instructions="Create final output based on analyzed data" +) + +# Create tasks for each step +initial_task = Task( + name="time_check", + description="Getting time check and checking if it is even or odd", + expected_output="Getting time check and checking if it is even or odd", + agent=agent1, + is_start=True, # Mark as the starting task + task_type="decision", # This task will make a decision + next_tasks=["advanced_analysis"], # Next task if condition passes + condition={ + "even": ["advanced_analysis"], # If passes, go to advanced analysis + "odd": "" # If fails, exit the chain + } +) + +analysis_task = Task( + name="advanced_analysis", + description="Perform advanced analysis on the processed data", + expected_output="Analyzed data ready for final processing", + agent=agent2, + next_tasks=["final_processing"] +) + +final_task = Task( + name="final_processing", + description="Generate final output", + expected_output="Final processed result", + agent=agent3 +) + +# Create the workflow manager +workflow = PraisonAIAgents( + agents=[agent1, agent2, agent3], + tasks=[initial_task, analysis_task, final_task], + process="workflow", # Use workflow process type + verbose=True +) + +# Run the workflow +results = workflow.start() + +# Print results +print("\nWorkflow Results:") +for task_id, result in results["task_results"].items(): + if result: + print(f"Task {task_id}: {result.raw}") diff --git a/docs/api/praisonai/deploy.html b/docs/api/praisonai/deploy.html index 3c0aa76..6417215 100644 --- a/docs/api/praisonai/deploy.html +++ b/docs/api/praisonai/deploy.html @@ -110,7 +110,7 @@

Raises

file.write("FROM python:3.11-slim\n") file.write("WORKDIR /app\n") file.write("COPY . .\n") - file.write("RUN pip install flask praisonai==2.0.41 gunicorn markdown\n") + file.write("RUN pip install flask praisonai==2.0.42 gunicorn markdown\n") file.write("EXPOSE 8080\n") file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n') diff --git a/docs/features/promptchaining.mdx b/docs/features/promptchaining.mdx new file mode 100644 index 0000000..375c7e0 --- /dev/null +++ b/docs/features/promptchaining.mdx @@ -0,0 +1,248 @@ +--- +title: "Agentic Prompt Chaining" +description: "Learn how to create AI agents with sequential prompt chaining for complex workflows." +icon: "link" +--- + +## Quick Start + + + + First, install the PraisonAI Agents package: + ```bash + pip install praisonaiagents + ``` + + + + Set your OpenAI API key as an environment variable in your terminal: + ```bash + export OPENAI_API_KEY=your_api_key_here + ``` + + + + Create a new file `app.py` with the basic setup: + ```python + from praisonaiagents import Agent, Task, PraisonAIAgents + import time + + def get_time_check(): + current_time = int(time.time()) + result = "even" if current_time % 2 == 0 else "odd" + print(f"Time check: {current_time} is {result}") + return result + + # Create agents for each step in the chain + agent1 = Agent( + name="Time Checker", + role="Time checker", + goal="Check if the time is even or odd", + instructions="Check if the time is even or odd", + tools=[get_time_check] + ) + + agent2 = Agent( + name="Advanced Analyzer", + role="Advanced data analyzer", + goal="Perform in-depth analysis of processed data", + instructions="Analyze the processed data in detail" + ) + + agent3 = Agent( + name="Final Processor", + role="Final data processor", + goal="Generate final output based on analysis", + instructions="Create final output based on analyzed data" + ) + + # Create tasks for each step + initial_task = Task( + name="time_check", + description="Getting time check and checking if it is even or odd", + expected_output="Getting time check and checking if it is even or odd", + agent=agent1, + is_start=True, # Mark as the starting task + task_type="decision", # This task will make a decision + next_tasks=["advanced_analysis"], # Next task if condition passes + condition={ + "even": ["advanced_analysis"], # If passes, go to advanced analysis + "odd": "" # If fails, exit the chain + } + ) + + analysis_task = Task( + name="advanced_analysis", + description="Perform advanced analysis on the processed data", + expected_output="Analyzed data ready for final processing", + agent=agent2, + next_tasks=["final_processing"] + ) + + final_task = Task( + name="final_processing", + description="Generate final output", + expected_output="Final processed result", + agent=agent3 + ) + + # Create the workflow manager + workflow = PraisonAIAgents( + agents=[agent1, agent2, agent3], + tasks=[initial_task, analysis_task, final_task], + process="workflow", # Use workflow process type + verbose=True + ) + + # Run the workflow + results = workflow.start() + + # Print results + print("\nWorkflow Results:") + for task_id, result in results["task_results"].items(): + if result: + print(f"Task {task_id}: {result.raw}") + ``` + + + + Type this in your terminal to run your agents: + ```bash + python app.py + ``` + + + + + **Requirements** + - Python 3.10 or higher + - OpenAI API key. Generate OpenAI API key [here](https://platform.openai.com/api-keys). Use Other models using [this guide](/models). + - Basic understanding of Python + + +## Understanding Prompt Chaining + + + Prompt chaining enables: + - Sequential execution of prompts + - Data flow between agents + - Conditional branching in workflows + - Step-by-step processing of complex tasks + + +## Features + + + + Execute tasks in a defined sequence with data passing between steps. + + + Implement conditional logic to control workflow progression. + + + Pass data seamlessly between agents in the chain. + + + Monitor and control the execution of each step in the chain. + + + +## Configuration Options to exit the chain + +```python +# Task with chaining configuration +task = Task( + name="time_check", + description="Check time and make decision", + expected_output="Time check result", + agent=agent, + is_start=True, + task_type="decision", + next_tasks=["next_step"], + condition={ + "even": ["next_step"], + "odd": "" + } +) +``` + +```python +task = Task( + name="time_check", + description="Check time and make decision", + expected_output="Time check result", + agent=agent, + is_start=True, + task_type="decision", + next_tasks=["next_step"], + condition={ + "even": ["next_step"], + "odd": "exit" + } +) +``` + +```python +task = Task( + name="time_check", + description="Check time and make decision", + expected_output="Time check result", + agent=agent, + is_start=True, + task_type="decision", + next_tasks=["next_step"], + condition={ + "even": ["next_step"], + "odd": ["exit"] + } +) +``` + +```python +task = Task( + name="time_check", + description="Check time and make decision", + expected_output="Time check result", + agent=agent, + is_start=True, + task_type="decision", + next_tasks=["next_step"], + condition={ + "even": ["next_step"], + "odd": [""] + } +) +``` + +## Troubleshooting + + + + If chain execution fails: + - Verify task connections + - Check condition logic + - Enable verbose mode for debugging + + + + If data flow is incorrect: + - Review task outputs + - Check agent configurations + - Verify task dependencies + + + +## Next Steps + + + + Learn about automatically created and managed AI agents + + + Explore lightweight, focused AI agents + + + + + For optimal results, ensure your chain is properly configured with clear task dependencies and conditions for branching logic. + \ No newline at end of file diff --git a/praisonai.rb b/praisonai.rb index 37c7e5b..7c1b7d2 100644 --- a/praisonai.rb +++ b/praisonai.rb @@ -3,7 +3,7 @@ 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/2.0.41.tar.gz" + url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.42.tar.gz" sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum license "MIT" diff --git a/praisonai/deploy.py b/praisonai/deploy.py index 7690ea1..437904e 100644 --- a/praisonai/deploy.py +++ b/praisonai/deploy.py @@ -56,7 +56,7 @@ def create_dockerfile(self): file.write("FROM python:3.11-slim\n") file.write("WORKDIR /app\n") file.write("COPY . .\n") - file.write("RUN pip install flask praisonai==2.0.41 gunicorn markdown\n") + file.write("RUN pip install flask praisonai==2.0.42 gunicorn markdown\n") file.write("EXPOSE 8080\n") file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n') diff --git a/pyproject.toml b/pyproject.toml index 14110f9..203e909 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "PraisonAI" -version = "2.0.41" +version = "2.0.42" description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration." readme = "README.md" license = "" @@ -12,7 +12,7 @@ dependencies = [ "rich>=13.7", "markdown>=3.5", "pyparsing>=3.0.0", - "praisonaiagents>=0.0.31", + "praisonaiagents>=0.0.32", "python-dotenv>=0.19.0", "instructor>=1.3.3", "PyYAML>=6.0", @@ -84,7 +84,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.7", "crewai"] [tool.poetry] name = "PraisonAI" -version = "2.0.41" +version = "2.0.42" description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration." authors = ["Mervin Praison"] license = "" @@ -102,7 +102,7 @@ python = ">=3.10,<3.13" rich = ">=13.7" markdown = ">=3.5" pyparsing = ">=3.0.0" -praisonaiagents = ">=0.0.31" +praisonaiagents = ">=0.0.32" python-dotenv = ">=0.19.0" instructor = ">=1.3.3" PyYAML = ">=6.0" diff --git a/uv.lock b/uv.lock index d8124ab..dc65e7f 100644 --- a/uv.lock +++ b/uv.lock @@ -3060,7 +3060,7 @@ wheels = [ [[package]] name = "praisonai" -version = "2.0.41" +version = "2.0.42" source = { editable = "." } dependencies = [ { name = "instructor" }, @@ -3197,7 +3197,7 @@ requires-dist = [ { name = "plotly", marker = "extra == 'realtime'", specifier = ">=5.24.0" }, { name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.7" }, { name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.7" }, - { name = "praisonaiagents", specifier = ">=0.0.31" }, + { name = "praisonaiagents", specifier = ">=0.0.32" }, { name = "pyautogen", marker = "extra == 'autogen'", specifier = ">=0.2.19" }, { name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" }, { name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" }, @@ -3250,16 +3250,16 @@ wheels = [ [[package]] name = "praisonaiagents" -version = "0.0.31" +version = "0.0.32" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "openai" }, { name = "pydantic" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e6/33/3dbf92fd64ee405b9382e79f688cef390ff9164d72ead030f4246fb9d2d1/praisonaiagents-0.0.31.tar.gz", hash = "sha256:9c372c51c741a0365c1186b087b3a72f4371e6ae2c203fa072b7a89a400e2560", size = 68508 } +sdist = { url = "https://files.pythonhosted.org/packages/96/b7/3de3e4cff09a2b21f7b8c1555a7f3de8e4a00ff99e63bce778fe9429dc23/praisonaiagents-0.0.32.tar.gz", hash = "sha256:466f43cf9638baac3f1196870c88d02718c9a2f870fe712ee6cbbc8d6c61c6bc", size = 68653 } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/7e/6eea88722770bd5f2691d8a0669cc46746961db969ea58d1380ce9e31648/praisonaiagents-0.0.31-py3-none-any.whl", hash = "sha256:41445ca9ab38d26f01df0873837bf8436e7013020474808312eff06894f2ce8e", size = 85455 }, + { url = "https://files.pythonhosted.org/packages/50/a6/32e90fe57973b9ebdfcca1ff80fa0142c935517456aef8bdd8ef2118e311/praisonaiagents-0.0.32-py3-none-any.whl", hash = "sha256:f0175e2a8560d1bdc7c06b788d821422d403255fa3dd964ff5857f713e4972a1", size = 85596 }, ] [[package]]