praisonaiagents 0.0.27__py3-none-any.whl → 0.0.29__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,335 @@
1
+ """
2
+ AutoAgents - A class for automatically creating and managing AI agents and tasks.
3
+
4
+ This class provides a simplified interface for creating and running AI agents with tasks.
5
+ It automatically handles agent creation, task setup, and execution flow.
6
+ """
7
+
8
+ from .agents import PraisonAIAgents
9
+ from ..agent.agent import Agent
10
+ from ..task.task import Task
11
+ from typing import List, Any, Optional, Dict, Union
12
+ import logging
13
+ import os
14
+ from pydantic import BaseModel, Field
15
+ from ..main import display_instruction, display_tool_call, display_interaction, client
16
+
17
+ # Define Pydantic models for structured output
18
+ class TaskConfig(BaseModel):
19
+ name: str
20
+ description: str
21
+ expected_output: str
22
+ tools: List[str]
23
+
24
+ class AgentConfig(BaseModel):
25
+ name: str
26
+ role: str
27
+ goal: str
28
+ backstory: str
29
+ tools: List[str]
30
+ tasks: List[TaskConfig]
31
+
32
+ class AutoAgentsConfig(BaseModel):
33
+ main_instruction: str
34
+ process_type: str
35
+ agents: List[AgentConfig]
36
+
37
+ class AutoAgents(PraisonAIAgents):
38
+ def __init__(
39
+ self,
40
+ instructions: str,
41
+ tools: Optional[List[Any]] = None,
42
+ verbose: bool = False,
43
+ process: str = "sequential",
44
+ manager_llm: Optional[str] = None,
45
+ max_retries: int = 5,
46
+ completion_checker: Optional[Any] = None,
47
+ allow_code_execution: bool = False,
48
+ memory: bool = True,
49
+ markdown: bool = True,
50
+ self_reflect: bool = False,
51
+ max_reflect: int = 3,
52
+ min_reflect: int = 1,
53
+ llm: Optional[str] = None,
54
+ function_calling_llm: Optional[str] = None,
55
+ respect_context_window: bool = True,
56
+ code_execution_mode: str = "safe",
57
+ embedder_config: Optional[Dict[str, Any]] = None,
58
+ knowledge_sources: Optional[List[Any]] = None,
59
+ use_system_prompt: bool = True,
60
+ cache: bool = True,
61
+ allow_delegation: bool = False,
62
+ step_callback: Optional[Any] = None,
63
+ system_template: Optional[str] = None,
64
+ prompt_template: Optional[str] = None,
65
+ response_template: Optional[str] = None,
66
+ max_rpm: Optional[int] = None,
67
+ max_execution_time: Optional[int] = None,
68
+ max_iter: int = 20,
69
+ reflect_llm: Optional[str] = None,
70
+ base_url: Optional[str] = None,
71
+ api_key: Optional[str] = None,
72
+ max_agents: int = 3 # New parameter for maximum number of agents
73
+ ):
74
+ """Initialize AutoAgents with configuration for automatic agent and task creation."""
75
+ if max_agents < 1:
76
+ raise ValueError("max_agents must be at least 1")
77
+ if max_agents > 10:
78
+ raise ValueError("max_agents cannot exceed 10")
79
+
80
+ # Store all configuration parameters first
81
+ self.instructions = instructions
82
+ self.tools = tools or []
83
+ self.verbose = verbose # Store verbose parameter
84
+ self.max_agents = max_agents # Store max_agents parameter
85
+ self.allow_code_execution = allow_code_execution
86
+ self.memory = memory
87
+ self.markdown = markdown
88
+ self.self_reflect = self_reflect
89
+ self.max_reflect = max_reflect
90
+ self.min_reflect = min_reflect
91
+ self.llm = llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
92
+ self.function_calling_llm = function_calling_llm
93
+ self.respect_context_window = respect_context_window
94
+ self.code_execution_mode = code_execution_mode
95
+ self.embedder_config = embedder_config
96
+ self.knowledge_sources = knowledge_sources
97
+ self.use_system_prompt = use_system_prompt
98
+ self.cache = cache
99
+ self.allow_delegation = allow_delegation
100
+ self.step_callback = step_callback
101
+ self.system_template = system_template
102
+ self.prompt_template = prompt_template
103
+ self.response_template = response_template
104
+ self.max_rpm = max_rpm
105
+ self.max_execution_time = max_execution_time
106
+ self.max_iter = max_iter
107
+ self.reflect_llm = reflect_llm
108
+
109
+ # Display initial instruction
110
+ if self.verbose:
111
+ display_instruction(f"🎯 Main Task: {self.instructions}")
112
+ display_instruction(f"📊 Maximum Agents: {self.max_agents}")
113
+ if self.tools:
114
+ tool_names = [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools]
115
+ display_tool_call(f"🛠️ Available Tools: {', '.join(tool_names)}")
116
+
117
+ # Generate agents and tasks configuration
118
+ config = self._generate_config()
119
+ agents, tasks = self._create_agents_and_tasks(config)
120
+
121
+ # Display agents and their tasks
122
+ if self.verbose:
123
+ self._display_agents_and_tasks(agents, tasks)
124
+
125
+ # Initialize parent class with generated agents and tasks
126
+ super().__init__(
127
+ agents=agents,
128
+ tasks=tasks,
129
+ verbose=verbose,
130
+ completion_checker=completion_checker,
131
+ max_retries=max_retries,
132
+ process=process,
133
+ manager_llm=manager_llm
134
+ )
135
+
136
+ def _display_agents_and_tasks(self, agents: List[Agent], tasks: List[Task]):
137
+ """Display the created agents and their assigned tasks"""
138
+ display_instruction("\n🤖 Generated Agents and Tasks:")
139
+
140
+ # Create a mapping of agents to their tasks
141
+ agent_tasks = {}
142
+ for task in tasks:
143
+ if task.agent not in agent_tasks:
144
+ agent_tasks[task.agent] = []
145
+ agent_tasks[task.agent].append(task)
146
+
147
+ # Display each agent and their tasks
148
+ for agent in agents:
149
+ agent_tools = [t.__name__ if hasattr(t, '__name__') else str(t) for t in agent.tools]
150
+ display_interaction(
151
+ f"\n👤 Agent: {agent.name}",
152
+ f"""Role: {agent.role}
153
+ Goal: {agent.goal}
154
+ Tools: {', '.join(agent_tools)}"""
155
+ )
156
+
157
+ # Display tasks for this agent
158
+ if agent in agent_tasks:
159
+ for i, task in enumerate(agent_tasks[agent], 1):
160
+ task_tools = [t.__name__ if hasattr(t, '__name__') else str(t) for t in task.tools]
161
+ display_instruction(
162
+ f""" 📋 Task {i}: {task.name}
163
+ Description: {task.description}
164
+ Expected Output: {task.expected_output}
165
+ Tools: {', '.join(task_tools)}"""
166
+ )
167
+
168
+ def _get_available_tools(self) -> List[str]:
169
+ """Get list of available tools"""
170
+ if not self.tools:
171
+ return []
172
+ return [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools]
173
+
174
+ def _get_tool_by_name(self, tool_name: str) -> Optional[Any]:
175
+ """Get tool object by its name"""
176
+ for tool in self.tools:
177
+ if (hasattr(tool, '__name__') and tool.__name__ == tool_name) or str(tool) == tool_name:
178
+ return tool
179
+ return None
180
+
181
+ def _assign_tools_to_agent(self, agent_config: AgentConfig) -> List[Any]:
182
+ """
183
+ Assign appropriate tools to an agent based on its role and tasks.
184
+
185
+ Args:
186
+ agent_config: The agent configuration containing role and required tools
187
+
188
+ Returns:
189
+ List of tool objects assigned to this agent
190
+ """
191
+ assigned_tools = []
192
+ tool_names = set(agent_config.tools)
193
+
194
+ # Also look at task requirements
195
+ for task in agent_config.tasks:
196
+ tool_names.update(task.tools)
197
+
198
+ # Assign tools that match the requirements
199
+ for tool_name in tool_names:
200
+ tool = self._get_tool_by_name(tool_name)
201
+ if tool:
202
+ assigned_tools.append(tool)
203
+
204
+ # If no specific tools matched but we have tools available,
205
+ # assign all tools to ensure functionality
206
+ if not assigned_tools and self.tools:
207
+ assigned_tools = self.tools
208
+
209
+ return assigned_tools
210
+
211
+ def _generate_config(self) -> AutoAgentsConfig:
212
+ """Generate the configuration for agents and tasks"""
213
+ prompt = f"""
214
+ Generate a configuration for AI agents to accomplish this task: "{self.instructions}"
215
+
216
+ The configuration should include:
217
+ 1. A main instruction that clearly states the overall goal
218
+ 2. A process type (sequential, workflow, or hierarchical)
219
+ 3. A list of maximum {self.max_agents} agents (no more, no less), each with:
220
+ - Name, role, goal, and backstory
221
+ - List of required tools from: {self._get_available_tools()}
222
+ - Only add tools that are needed for the agent to perform its task
223
+ - Only one task per agent. Add more than one task if absolutely necessary.
224
+ - List of specific tasks they need to perform
225
+ - Whether they should self-reflect or allow delegation
226
+
227
+ Requirements:
228
+ 1. Each agent should have clear, focused responsibilities
229
+ 2. Tasks should be broken down into manageable steps
230
+ 3. Tool selection should be appropriate for each task
231
+ 4. The process type should match the task requirements
232
+ 5. Generate maximum {self.max_agents} agents to handle this task efficiently
233
+
234
+ Return the configuration in a structured JSON format matching the AutoAgentsConfig schema.
235
+ """
236
+
237
+ try:
238
+ response = client.beta.chat.completions.parse(
239
+ model=self.llm,
240
+ response_format=AutoAgentsConfig,
241
+ messages=[
242
+ {"role": "system", "content": "You are a helpful assistant designed to generate AI agent configurations."},
243
+ {"role": "user", "content": prompt}
244
+ ]
245
+ )
246
+
247
+ # Ensure we have exactly max_agents number of agents
248
+ if len(response.choices[0].message.parsed.agents) > self.max_agents:
249
+ response.choices[0].message.parsed.agents = response.choices[0].message.parsed.agents[:self.max_agents]
250
+ elif len(response.choices[0].message.parsed.agents) < self.max_agents:
251
+ logging.warning(f"Generated {len(response.choices[0].message.parsed.agents)} agents, expected {self.max_agents}")
252
+
253
+ return response.choices[0].message.parsed
254
+ except Exception as e:
255
+ logging.error(f"Error generating configuration: {e}")
256
+ raise
257
+
258
+ def _create_agents_and_tasks(self, config: AutoAgentsConfig) -> tuple[List[Agent], List[Task]]:
259
+ """Create agents and tasks from configuration"""
260
+ agents = []
261
+ tasks = []
262
+
263
+ for agent_config in config.agents:
264
+ # Get appropriate tools for this agent
265
+ agent_tools = self._assign_tools_to_agent(agent_config)
266
+
267
+ # Create the agent with all parameters
268
+ agent = Agent(
269
+ name=agent_config.name,
270
+ role=agent_config.role,
271
+ goal=agent_config.goal,
272
+ backstory=agent_config.backstory,
273
+ tools=agent_tools, # Use assigned tools
274
+ verbose=self.verbose >= 1,
275
+ allow_code_execution=self.allow_code_execution,
276
+ memory=self.memory,
277
+ markdown=self.markdown,
278
+ self_reflect=self.self_reflect,
279
+ max_reflect=self.max_reflect,
280
+ min_reflect=self.min_reflect,
281
+ llm=self.llm,
282
+ function_calling_llm=self.function_calling_llm,
283
+ respect_context_window=self.respect_context_window,
284
+ code_execution_mode=self.code_execution_mode,
285
+ embedder_config=self.embedder_config,
286
+ knowledge_sources=self.knowledge_sources,
287
+ use_system_prompt=self.use_system_prompt,
288
+ cache=self.cache,
289
+ allow_delegation=self.allow_delegation,
290
+ step_callback=self.step_callback,
291
+ system_template=self.system_template,
292
+ prompt_template=self.prompt_template,
293
+ response_template=self.response_template,
294
+ max_rpm=self.max_rpm,
295
+ max_execution_time=self.max_execution_time,
296
+ max_iter=self.max_iter,
297
+ reflect_llm=self.reflect_llm
298
+ )
299
+ agents.append(agent)
300
+
301
+ # Create tasks for this agent
302
+ for task_config in agent_config.tasks:
303
+ # Get task-specific tools
304
+ task_tools = [self._get_tool_by_name(t) for t in task_config.tools]
305
+ task_tools = [t for t in task_tools if t] # Remove None values
306
+
307
+ # If no specific tools matched, use agent's tools
308
+ if not task_tools:
309
+ task_tools = agent_tools
310
+
311
+ task = Task(
312
+ name=task_config.name,
313
+ description=task_config.description,
314
+ expected_output=task_config.expected_output,
315
+ agent=agent,
316
+ tools=task_tools # Use task-specific tools
317
+ )
318
+ tasks.append(task)
319
+
320
+ return agents, tasks
321
+
322
+ async def astart(self):
323
+ """
324
+ Async version of start() method.
325
+ Creates tasks based on the instructions, then starts execution.
326
+ Returns the task status and results dictionary.
327
+ """
328
+ return await super().astart()
329
+
330
+ def start(self):
331
+ """
332
+ Creates tasks based on the instructions, then starts execution.
333
+ Returns the task status and results dictionary.
334
+ """
335
+ return super().start()