praisonaiagents 0.0.88__tar.gz → 0.0.90__tar.gz

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.
Files changed (52) hide show
  1. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/PKG-INFO +2 -1
  2. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/agents/autoagents.py +6 -4
  3. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/main.py +2 -1
  4. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/process/process.py +44 -39
  5. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/task/task.py +15 -2
  6. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents.egg-info/PKG-INFO +2 -1
  7. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents.egg-info/SOURCES.txt +2 -1
  8. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/pyproject.toml +6 -2
  9. praisonaiagents-0.0.90/tests/test.py +147 -0
  10. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/README.md +0 -0
  11. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/__init__.py +0 -0
  12. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/agent/__init__.py +0 -0
  13. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/agent/agent.py +0 -0
  14. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/agent/image_agent.py +0 -0
  15. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/agents/__init__.py +0 -0
  16. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/agents/agents.py +0 -0
  17. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/knowledge/__init__.py +0 -0
  18. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/knowledge/chunking.py +0 -0
  19. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/knowledge/knowledge.py +0 -0
  20. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/llm/__init__.py +0 -0
  21. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/llm/llm.py +0 -0
  22. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/mcp/__init__.py +0 -0
  23. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/mcp/mcp.py +0 -0
  24. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/mcp/mcp_sse.py +0 -0
  25. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/memory/memory.py +0 -0
  26. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/process/__init__.py +0 -0
  27. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/task/__init__.py +0 -0
  28. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/__init__.py +0 -0
  29. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/arxiv_tools.py +0 -0
  30. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/calculator_tools.py +0 -0
  31. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/csv_tools.py +0 -0
  32. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/duckdb_tools.py +0 -0
  33. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/duckduckgo_tools.py +0 -0
  34. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/excel_tools.py +0 -0
  35. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/file_tools.py +0 -0
  36. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/json_tools.py +0 -0
  37. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/newspaper_tools.py +0 -0
  38. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/pandas_tools.py +0 -0
  39. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/python_tools.py +0 -0
  40. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/shell_tools.py +0 -0
  41. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/spider_tools.py +0 -0
  42. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/test.py +0 -0
  43. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/tools.py +0 -0
  44. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/train/data/generatecot.py +0 -0
  45. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/wikipedia_tools.py +0 -0
  46. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/xml_tools.py +0 -0
  47. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/yaml_tools.py +0 -0
  48. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents/tools/yfinance_tools.py +0 -0
  49. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents.egg-info/dependency_links.txt +0 -0
  50. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents.egg-info/requires.txt +0 -0
  51. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/praisonaiagents.egg-info/top_level.txt +0 -0
  52. {praisonaiagents-0.0.88 → praisonaiagents-0.0.90}/setup.cfg +0 -0
@@ -1,8 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.88
3
+ Version: 0.0.90
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
+ Requires-Python: >=3.10
6
7
  Requires-Dist: pydantic
7
8
  Requires-Dist: rich
8
9
  Requires-Dist: openai
@@ -8,10 +8,10 @@ It automatically handles agent creation, task setup, and execution flow.
8
8
  from .agents import PraisonAIAgents
9
9
  from ..agent.agent import Agent
10
10
  from ..task.task import Task
11
- from typing import List, Any, Optional, Dict
11
+ from typing import List, Any, Optional, Dict, Tuple
12
12
  import logging
13
13
  import os
14
- from pydantic import BaseModel
14
+ from pydantic import BaseModel, ConfigDict
15
15
  from ..main import display_instruction, display_tool_call, display_interaction, client
16
16
 
17
17
  # Define Pydantic models for structured output
@@ -22,6 +22,7 @@ class TaskConfig(BaseModel):
22
22
  tools: List[str]
23
23
 
24
24
  class AgentConfig(BaseModel):
25
+ model_config = ConfigDict(arbitrary_types_allowed=True)
25
26
  name: str
26
27
  role: str
27
28
  goal: str
@@ -30,6 +31,7 @@ class AgentConfig(BaseModel):
30
31
  tasks: List[TaskConfig]
31
32
 
32
33
  class AutoAgentsConfig(BaseModel):
34
+ model_config = ConfigDict(arbitrary_types_allowed=True)
33
35
  main_instruction: str
34
36
  process_type: str
35
37
  agents: List[AgentConfig]
@@ -255,7 +257,7 @@ Return the configuration in a structured JSON format matching the AutoAgentsConf
255
257
  logging.error(f"Error generating configuration: {e}")
256
258
  raise
257
259
 
258
- def _create_agents_and_tasks(self, config: AutoAgentsConfig) -> tuple[List[Agent], List[Task]]:
260
+ def _create_agents_and_tasks(self, config: AutoAgentsConfig) -> Tuple[List[Agent], List[Task]]:
259
261
  """Create agents and tasks from configuration"""
260
262
  agents = []
261
263
  tasks = []
@@ -283,7 +285,7 @@ Return the configuration in a structured JSON format matching the AutoAgentsConf
283
285
  respect_context_window=self.respect_context_window,
284
286
  code_execution_mode=self.code_execution_mode,
285
287
  embedder_config=self.embedder_config,
286
- knowledge_sources=self.knowledge_sources,
288
+ knowledge=self.knowledge_sources,
287
289
  use_system_prompt=self.use_system_prompt,
288
290
  cache=self.cache,
289
291
  allow_delegation=self.allow_delegation,
@@ -4,7 +4,7 @@ import json
4
4
  import logging
5
5
  from typing import List, Optional, Dict, Any, Union, Literal, Type
6
6
  from openai import OpenAI
7
- from pydantic import BaseModel
7
+ from pydantic import BaseModel, ConfigDict
8
8
  from rich import print
9
9
  from rich.console import Console
10
10
  from rich.panel import Panel
@@ -365,6 +365,7 @@ class ReflectionOutput(BaseModel):
365
365
  client = OpenAI(api_key=(os.environ["OPENAI_API_KEY"] if os.environ.get("OPENAI_API_KEY") else "xxxx"))
366
366
 
367
367
  class TaskOutput(BaseModel):
368
+ model_config = ConfigDict(arbitrary_types_allowed=True)
368
369
  description: str
369
370
  summary: Optional[str] = None
370
371
  raw: str
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import asyncio
3
3
  from typing import Dict, Optional, List, Any, AsyncGenerator
4
- from pydantic import BaseModel
4
+ from pydantic import BaseModel, ConfigDict
5
5
  from ..agent.agent import Agent
6
6
  from ..task.task import Task
7
7
  from ..main import display_error, client
@@ -9,6 +9,7 @@ import csv
9
9
  import os
10
10
 
11
11
  class LoopItems(BaseModel):
12
+ model_config = ConfigDict(arbitrary_types_allowed=True)
12
13
  items: List[Any]
13
14
 
14
15
  class Process:
@@ -30,6 +31,44 @@ class Process:
30
31
  self.task_retry_counter: Dict[str, int] = {} # Initialize retry counter
31
32
  self.workflow_finished = False # ADDED: Workflow finished flag
32
33
 
34
+ def _build_task_context(self, current_task: Task) -> str:
35
+ """Build context for a task based on its retain_full_context setting"""
36
+ if not (current_task.previous_tasks or current_task.context):
37
+ return ""
38
+
39
+ context = "\nInput data from previous tasks:"
40
+
41
+ if current_task.retain_full_context:
42
+ # Original behavior: include all previous tasks
43
+ for prev_name in current_task.previous_tasks:
44
+ prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
45
+ if prev_task and prev_task.result:
46
+ context += f"\n{prev_name}: {prev_task.result.raw}"
47
+
48
+ # Add data from context tasks
49
+ if current_task.context:
50
+ for ctx_task in current_task.context:
51
+ if ctx_task.result and ctx_task.name != current_task.name:
52
+ context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
53
+ else:
54
+ # New behavior: only include the most recent previous task
55
+ if current_task.previous_tasks:
56
+ # Get the most recent previous task (last in the list)
57
+ prev_name = current_task.previous_tasks[-1]
58
+ prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
59
+ if prev_task and prev_task.result:
60
+ context += f"\n{prev_name}: {prev_task.result.raw}"
61
+
62
+ # For context tasks, still include the most recent one
63
+ if current_task.context:
64
+ # Get the most recent context task with a result
65
+ for ctx_task in reversed(current_task.context):
66
+ if ctx_task.result and ctx_task.name != current_task.name:
67
+ context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
68
+ break # Only include the most recent one
69
+
70
+ return context
71
+
33
72
  def _find_next_not_started_task(self) -> Optional[Task]:
34
73
  """Fallback mechanism to find the next 'not started' task."""
35
74
  fallback_attempts = 0
@@ -147,25 +186,8 @@ Description length: {len(current_task.description)}
147
186
  """)
148
187
 
149
188
  # Add context from previous tasks to description
150
- if current_task.previous_tasks or current_task.context:
151
- context = "\nInput data from previous tasks:"
152
-
153
- # Add data from previous tasks in workflow
154
- for prev_name in current_task.previous_tasks:
155
- prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
156
- if prev_task and prev_task.result:
157
- # Handle loop data
158
- if current_task.task_type == "loop":
159
- context += f"\n{prev_name}: {prev_task.result.raw}"
160
- else:
161
- context += f"\n{prev_name}: {prev_task.result.raw}"
162
-
163
- # Add data from context tasks
164
- if current_task.context:
165
- for ctx_task in current_task.context:
166
- if ctx_task.result and ctx_task.name != current_task.name:
167
- context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
168
-
189
+ context = self._build_task_context(current_task)
190
+ if context:
169
191
  # Update task description with context
170
192
  current_task.description = current_task.description + context
171
193
 
@@ -778,25 +800,8 @@ Description length: {len(current_task.description)}
778
800
  """)
779
801
 
780
802
  # Add context from previous tasks to description
781
- if current_task.previous_tasks or current_task.context:
782
- context = "\nInput data from previous tasks:"
783
-
784
- # Add data from previous tasks in workflow
785
- for prev_name in current_task.previous_tasks:
786
- prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
787
- if prev_task and prev_task.result:
788
- # Handle loop data
789
- if current_task.task_type == "loop":
790
- context += f"\n{prev_name}: {prev_task.result.raw}"
791
- else:
792
- context += f"\n{prev_name}: {prev_task.result.raw}"
793
-
794
- # Add data from context tasks
795
- if current_task.context:
796
- for ctx_task in current_task.context:
797
- if ctx_task.result and ctx_task.name != current_task.name:
798
- context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
799
-
803
+ context = self._build_task_context(current_task)
804
+ if context:
800
805
  # Update task description with context
801
806
  current_task.description = current_task.description + context
802
807
 
@@ -39,7 +39,8 @@ class Task:
39
39
  memory=None,
40
40
  quality_check=True,
41
41
  input_file: Optional[str] = None,
42
- rerun: bool = False # Renamed from can_rerun and logic inverted, default True for backward compatibility
42
+ rerun: bool = False, # Renamed from can_rerun and logic inverted, default True for backward compatibility
43
+ retain_full_context: bool = False # By default, only use previous task output, not all previous tasks
43
44
  ):
44
45
  # Add check if memory config is provided
45
46
  if memory is not None or (config and config.get('memory_config')):
@@ -78,6 +79,7 @@ class Task:
78
79
  self.memory = memory
79
80
  self.quality_check = quality_check
80
81
  self.rerun = rerun # Assigning the rerun parameter
82
+ self.retain_full_context = retain_full_context
81
83
 
82
84
  # Set logger level based on config verbose level
83
85
  verbose = self.config.get("verbose", 0)
@@ -213,9 +215,20 @@ class Task:
213
215
  logger.info(f"Task {self.id}: Calculating quality metrics for output: {task_output.raw[:100]}...")
214
216
 
215
217
  # Get quality metrics from LLM
218
+ # Determine which LLM model to use based on agent configuration
219
+ llm_model = None
220
+ if self.agent:
221
+ if getattr(self.agent, '_using_custom_llm', False) and hasattr(self.agent, 'llm_instance'):
222
+ # For custom LLM instances (like Ollama)
223
+ llm_model = self.agent.llm_instance
224
+ elif hasattr(self.agent, 'llm') and self.agent.llm:
225
+ # For standard model strings
226
+ llm_model = self.agent.llm
227
+
216
228
  metrics = self.memory.calculate_quality_metrics(
217
229
  task_output.raw,
218
- self.expected_output
230
+ self.expected_output,
231
+ llm=llm_model
219
232
  )
220
233
  logger.info(f"Task {self.id}: Quality metrics calculated: {metrics}")
221
234
 
@@ -1,8 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.88
3
+ Version: 0.0.90
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
+ Requires-Python: >=3.10
6
7
  Requires-Dist: pydantic
7
8
  Requires-Dist: rich
8
9
  Requires-Dist: openai
@@ -46,4 +46,5 @@ praisonaiagents/tools/wikipedia_tools.py
46
46
  praisonaiagents/tools/xml_tools.py
47
47
  praisonaiagents/tools/yaml_tools.py
48
48
  praisonaiagents/tools/yfinance_tools.py
49
- praisonaiagents/tools/train/data/generatecot.py
49
+ praisonaiagents/tools/train/data/generatecot.py
50
+ tests/test.py
@@ -4,8 +4,9 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "praisonaiagents"
7
- version = "0.0.88"
7
+ version = "0.0.90"
8
8
  description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
9
+ requires-python = ">=3.10"
9
10
  authors = [
10
11
  { name="Mervin Praison" }
11
12
  ]
@@ -53,4 +54,7 @@ all = [
53
54
  "praisonaiagents[llm]",
54
55
  "praisonaiagents[mcp]",
55
56
  "praisonaiagents[api]"
56
- ]
57
+ ]
58
+
59
+ [tool.setuptools]
60
+ packages = ["praisonaiagents"]
@@ -0,0 +1,147 @@
1
+ from typing import List, Dict
2
+ from pydantic import BaseModel
3
+ from praisonaiagents import Agent, Task, PraisonAIAgents
4
+ from praisonaiagents.main import TaskOutput
5
+
6
+ # Pydantic models for structured output
7
+ class Chapter(BaseModel):
8
+ chapter_number: int
9
+ title: str
10
+ outline: str
11
+
12
+ class StoryOutline(BaseModel):
13
+ title: str
14
+ total_chapters: int
15
+ chapters: List[Chapter]
16
+
17
+ class ChapterContent(BaseModel):
18
+ chapter_number: int
19
+ title: str
20
+ content: str
21
+
22
+ # Create the story planner agent
23
+ planner_agent = Agent(
24
+ name="Story Planner",
25
+ role="Creative Writing Architect",
26
+ goal="Create detailed story outlines with chapter breakdowns",
27
+ backstory="Expert storyteller skilled in narrative structure and plot development",
28
+ verbose=True,
29
+ llm="gpt-4o-mini",
30
+ self_reflect=False
31
+ )
32
+
33
+ # Create the writer agent
34
+ writer_agent = Agent(
35
+ name="Story Writer",
36
+ role="Creative Writer",
37
+ goal="Write engaging and cohesive story chapters",
38
+ backstory="Experienced writer skilled in bringing stories to life with vivid details and engaging narrative",
39
+ verbose=True,
40
+ llm="gpt-4o-mini",
41
+ self_reflect=False
42
+ )
43
+
44
+ # Story title
45
+ story_title = "The Curious Cat"
46
+
47
+ # Step 1: Create outline task
48
+ outline_task = Task(
49
+ name="story_outline",
50
+ description=f"""Create a detailed story outline for a story titled '{story_title}'.
51
+ The outline should include:
52
+ 1. A compelling story arc
53
+ 2. Clear chapter breakdown
54
+ 3. Brief description of what happens in each chapter
55
+ 4. Character introductions and development points
56
+
57
+ Provide the response in this exact JSON format:
58
+ {{
59
+ "title": "Story title",
60
+ "total_chapters": number,
61
+ "chapters": [
62
+ {{
63
+ "chapter_number": 1,
64
+ "title": "Chapter title",
65
+ "outline": "Detailed chapter outline"
66
+ }}
67
+ ]
68
+ }}
69
+ """,
70
+ expected_output="Complete story outline",
71
+ agent=planner_agent,
72
+ output_pydantic=StoryOutline
73
+ )
74
+
75
+ # Create initial workflow for outline
76
+ outline_workflow = PraisonAIAgents(
77
+ agents=[planner_agent],
78
+ tasks=[outline_task],
79
+ verbose=True,
80
+ process="sequential"
81
+ )
82
+
83
+ # Get the outline
84
+ outline_result = outline_workflow.start()
85
+ story_outline = outline_result["task_results"][0].pydantic
86
+
87
+ # Step 2: Create tasks for each chapter
88
+ chapter_tasks = []
89
+ chapters_content = []
90
+
91
+ # Create a task for each chapter
92
+ for chapter in story_outline.chapters:
93
+ chapter_task = Task(
94
+ name=f"write_chapter_{chapter.chapter_number}",
95
+ description=f"""Write chapter {chapter.chapter_number}: {chapter.title}
96
+ Chapter outline: {chapter.outline}
97
+
98
+ Write a complete, engaging chapter following this outline.
99
+ Return in this exact JSON format:
100
+ {{
101
+ "chapter_number": {chapter.chapter_number},
102
+ "title": "{chapter.title}",
103
+ "content": "The full chapter content..."
104
+ }}
105
+ """,
106
+ expected_output="Complete chapter content",
107
+ agent=writer_agent,
108
+ output_pydantic=ChapterContent,
109
+ context=[outline_task]
110
+ )
111
+ chapter_tasks.append(chapter_task)
112
+
113
+ # Create sequential workflow for chapters
114
+ chapter_workflow = PraisonAIAgents(
115
+ agents=[writer_agent],
116
+ tasks=chapter_tasks,
117
+ verbose=True,
118
+ process="sequential"
119
+ )
120
+
121
+ # Run the chapter workflow
122
+ chapter_results = chapter_workflow.start()
123
+
124
+ # Collect and validate all chapter contents
125
+ for task_result in chapter_results["task_results"].values():
126
+ if task_result and task_result.pydantic:
127
+ chapters_content.append(task_result.pydantic)
128
+
129
+ # Sort chapters by chapter number
130
+ chapters_content.sort(key=lambda x: x.chapter_number)
131
+
132
+ # Format final result
133
+ story = {
134
+ "title": story_outline.title,
135
+ "outline": story_outline.model_dump(),
136
+ "chapters": [chapter.model_dump() for chapter in chapters_content]
137
+ }
138
+
139
+ # Print results
140
+ print("\n=== Story Generation Results ===")
141
+ print(f"\nTitle: {story['title']}")
142
+ print("\nOutline:")
143
+ print(story['outline'])
144
+ print("\nChapters:")
145
+ for chapter in story['chapters']:
146
+ print(f"\nChapter {chapter['chapter_number']}: {chapter['title']}")
147
+ print(chapter['content'][:200] + "...") # Print first 200 chars of each chapter