Compare commits

...
6 Commits
Author SHA1 Message Date
Mervin Praison d278f2d2b2 Merge pull request #399 from MervinPraison/develop
Bump version to 2.0.80 and update praisonaiagents dependency
2025-02-28 10:25:47 +00:00
MervinPraison df4596a699 Bump version to 2.0.80 and update praisonaiagents dependency
- Updated version to 2.0.80 across multiple files including praisonai.rb, pyproject.toml, uv.lock, Dockerfile, and docs
- Upgraded praisonaiagents dependency from 0.0.64 to 0.0.65
- Enhanced agent start methods with optional return_dict parameter
- Improved result handling in start and astart methods to return final response by default
- Synchronized version updates across project configuration files
2025-02-28 10:25:32 +00:00
Mervin Praison dd0f47ec81 Merge pull request #398 from MervinPraison/develop
Bump version to 2.0.79 and update praisonaiagents dependency
2025-02-28 07:26:52 +00:00
MervinPraison e53017a2fe Bump version to 2.0.79 and update praisonaiagents dependency
- Updated version to 2.0.79 across multiple files including praisonai.rb, pyproject.toml, uv.lock, Dockerfile, and docs
- Upgraded praisonaiagents dependency from 0.0.63 to 0.0.64
- Updated example agent scripts for Anthropic and Gemini LLMs
- Added parameter modification support in LLM initialization
- Synchronized version updates across project configuration files
2025-02-28 07:26:22 +00:00
Mervin Praison fe034ba8f4 Merge pull request #397 from MervinPraison/develop
Enhance Agent Tool Execution Logging and Debugging
2025-02-28 07:05:13 +00:00
MervinPraison 063e5780d6 Enhance Agent Tool Execution Logging and Debugging
- Added comprehensive debug logging for tool execution in LLM and Agent components
- Improved display of tool call messages with more detailed information
- Added logging for empty content and tool execution scenarios
- Enhanced error handling and logging in display functions
- Added new Anthropic LLM example script in src/praisonai-agents
- Bumped version to 2.0.78 and updated praisonaiagents dependency to 0.0.63
2025-02-28 07:04:50 +00:00
13 changed files with 139 additions and 39 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install flask praisonai==2.0.77 gunicorn markdown
RUN pip install flask praisonai==2.0.80 gunicorn markdown
EXPOSE 8080
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
+1 -1
View File
@@ -110,7 +110,7 @@ Loads environment variables from .env file or system and sets them.</p>
file.write(&#34;FROM python:3.11-slim\n&#34;)
file.write(&#34;WORKDIR /app\n&#34;)
file.write(&#34;COPY . .\n&#34;)
file.write(&#34;RUN pip install flask praisonai==2.0.77 gunicorn markdown\n&#34;)
file.write(&#34;RUN pip install flask praisonai==2.0.80 gunicorn markdown\n&#34;)
file.write(&#34;EXPOSE 8080\n&#34;)
file.write(&#39;CMD [&#34;gunicorn&#34;, &#34;-b&#34;, &#34;0.0.0.0:8080&#34;, &#34;api:app&#34;]\n&#39;)
+1 -1
View File
@@ -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.77.tar.gz"
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.80.tar.gz"
sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum
license "MIT"
+1 -1
View File
@@ -56,7 +56,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.0.77 gunicorn markdown\n")
file.write("RUN pip install flask praisonai==2.0.80 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
+4 -4
View File
@@ -1,6 +1,6 @@
[project]
name = "PraisonAI"
version = "2.0.77"
version = "2.0.80"
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.62",
"praisonaiagents>=0.0.65",
"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.77"
version = "2.0.80"
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.62"
praisonaiagents = ">=0.0.65"
python-dotenv = ">=0.19.0"
instructor = ">=1.3.3"
PyYAML = ">=6.0"
+37
View File
@@ -0,0 +1,37 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are a Wikipedia Agent",
llm="anthropic/claude-3-7-sonnet-20250219"
)
result = agent.start("Why Sky is Blue?")
print(result)
from praisonaiagents import Agent
from praisonaiagents.tools import internet_search
agent = Agent(
instructions="You are a Wikipedia Agent",
tools=[internet_search],
llm="anthropic/claude-3-7-sonnet-20250219"
)
agent.start("What is Praison AI?")
from praisonaiagents import Agent, PraisonAIAgents
from praisonaiagents.tools import internet_search
research_agent = Agent(
instructions="Search Information about Claude Sonnet 3.7",
tools=[internet_search],
llm="anthropic/claude-3-7-sonnet-20250219"
)
editor_agent = Agent(
instructions="Write a Blog Post with the provided information about Claude Sonnet 3.7",
llm="anthropic/claude-3-7-sonnet-20250219"
)
agents = PraisonAIAgents(agents=[research_agent, editor_agent])
result = agents.start()
print(result)
+4 -4
View File
@@ -1,10 +1,10 @@
from praisonaiagents import Agent
from praisonaiagents.tools import internet_search
agent = Agent(
instructions="You are a helpful assistant",
llm="gemini/gemini-1.5-flash-8b",
self_reflect=True,
verbose=True
tools=[internet_search],
llm="gemini/gemini-1.5-flash-8b"
)
agent.start("Why sky is Blue?")
agent.start("What is Praison AI?")
@@ -477,8 +477,14 @@ Context:
else:
self.run_task(task_id)
async def astart(self, content=None, **kwargs):
"""Async version of start method"""
async def astart(self, content=None, return_dict=False, **kwargs):
"""Async version of start method
Args:
content: Optional content to add to all tasks' context
return_dict: If True, returns the full results dictionary instead of only the final response
**kwargs: Additional arguments
"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
@@ -488,10 +494,25 @@ Context:
task.context.append(content)
await self.arun_all_tasks()
return {
# Get results
results = {
"task_status": self.get_all_tasks_status(),
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
}
# By default, return only the final agent's response
if not return_dict:
# Get the last task (assuming sequential processing)
task_ids = list(self.tasks.keys())
if task_ids:
last_task_id = task_ids[-1]
last_result = self.get_task_result(last_task_id)
if last_result:
return last_result.raw
# Return full results dict if return_dict is True or if no final result was found
return results
def save_output_to_file(self, task, task_output):
if task.output_file:
@@ -801,8 +822,14 @@ Context:
return str(agent[0])
return None
def start(self, content=None, **kwargs):
"""Start agent execution with optional content and config"""
def start(self, content=None, return_dict=False, **kwargs):
"""Start agent execution with optional content and config
Args:
content: Optional content to add to all tasks' context
return_dict: If True, returns the full results dictionary instead of only the final response
**kwargs: Additional arguments
"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
@@ -815,10 +842,25 @@ Context:
# Run tasks as before
self.run_all_tasks()
return {
# Get results
results = {
"task_status": self.get_all_tasks_status(),
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
}
# By default, return only the final agent's response
if not return_dict:
# Get the last task (assuming sequential processing)
task_ids = list(self.tasks.keys())
if task_ids:
last_task_id = task_ids[-1]
last_result = self.get_task_result(last_task_id)
if last_result:
return last_result.raw
# Return full results dict if return_dict is True or if no final result was found
return results
def set_state(self, key: str, value: Any) -> None:
"""Set a state value"""
+24 -12
View File
@@ -171,6 +171,8 @@ class LLM:
# Enable error dropping for cleaner output
litellm.drop_params = True
# Enable parameter modification for providers like Anthropic
litellm.modify_params = True
self._setup_event_tracking(events)
# Log all initialization parameters when in debug mode
@@ -438,20 +440,29 @@ class LLM:
function_name = tool_call["function"]["name"]
arguments = json.loads(tool_call["function"]["arguments"])
if verbose:
display_tool_call(f"Agent {agent_name} is calling function '{function_name}' with arguments: {arguments}", console=console)
logging.debug(f"[TOOL_EXEC_DEBUG] About to execute tool {function_name} with args: {arguments}")
tool_result = execute_tool_fn(function_name, arguments)
logging.debug(f"[TOOL_EXEC_DEBUG] Tool execution result: {tool_result}")
if tool_result:
if verbose:
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=console)
if verbose:
display_message = f"Agent {agent_name} called function '{function_name}' with arguments: {arguments}\n"
if tool_result:
display_message += f"Function returned: {tool_result}"
logging.debug(f"[TOOL_EXEC_DEBUG] Display message with result: {display_message}")
else:
display_message += "Function returned no output"
logging.debug("[TOOL_EXEC_DEBUG] Tool returned no output")
logging.debug(f"[TOOL_EXEC_DEBUG] About to display tool call with message: {display_message}")
display_tool_call(display_message, console=console)
messages.append({
"role": "tool",
"tool_call_id": tool_call["id"],
"content": json.dumps(tool_result)
})
else:
logging.debug("[TOOL_EXEC_DEBUG] Verbose mode off, not displaying tool call")
messages.append({
"role": "tool",
"tool_call_id": tool_call["id"],
@@ -923,14 +934,15 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
if verbose:
display_tool_call(f"Agent {agent_name} is calling function '{function_name}' with arguments: {arguments}", console=console)
tool_result = await execute_tool_fn(function_name, arguments)
if tool_result:
if verbose:
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=console)
if verbose:
display_message = f"Agent {agent_name} called function '{function_name}' with arguments: {arguments}\n"
if tool_result:
display_message += f"Function returned: {tool_result}"
else:
display_message += "Function returned no output"
display_tool_call(display_message, console=console)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
+11 -2
View File
@@ -86,6 +86,7 @@ async def execute_callback(display_type: str, **kwargs):
def _clean_display_content(content: str, max_length: int = 20000) -> str:
"""Helper function to clean and truncate content for display."""
if not content or not str(content).strip():
logging.debug(f"Empty content received in _clean_display_content: {repr(content)}")
return ""
content = str(content)
@@ -174,11 +175,14 @@ def display_instruction(message: str, console=None, agent_name: str = None, agen
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
def display_tool_call(message: str, console=None):
logging.debug(f"display_tool_call called with message: {repr(message)}")
if not message or not message.strip():
logging.debug("Empty message in display_tool_call, returning early")
return
if console is None:
console = Console()
message = _clean_display_content(str(message))
logging.debug(f"Cleaned message in display_tool_call: {repr(message)}")
# Execute callback if registered
if 'tool_call' in sync_display_callbacks:
@@ -202,7 +206,8 @@ def display_error(message: str, console=None):
def display_generating(content: str = "", start_time: Optional[float] = None):
if not content or not str(content).strip():
return Panel("", title="", border_style="green")
logging.debug("Empty content in display_generating, returning early")
return None
elapsed_str = ""
if start_time is not None:
@@ -293,11 +298,14 @@ async def adisplay_instruction(message: str, console=None, agent_name: str = Non
async def adisplay_tool_call(message: str, console=None):
"""Async version of display_tool_call."""
logging.debug(f"adisplay_tool_call called with message: {repr(message)}")
if not message or not message.strip():
logging.debug("Empty message in adisplay_tool_call, returning early")
return
if console is None:
console = Console()
message = _clean_display_content(str(message))
logging.debug(f"Cleaned message in adisplay_tool_call: {repr(message)}")
if 'tool_call' in async_display_callbacks:
await async_display_callbacks['tool_call'](message=message)
@@ -321,7 +329,8 @@ async def adisplay_error(message: str, console=None):
async def adisplay_generating(content: str = "", start_time: Optional[float] = None):
"""Async version of display_generating."""
if not content or not str(content).strip():
return Panel("", title="", border_style="green")
logging.debug("Empty content in adisplay_generating, returning early")
return None
elapsed_str = ""
if start_time is not None:
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.0.62"
version = "0.0.65"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
authors = [
{ name="Mervin Praison" }
+1 -1
View File
@@ -1868,7 +1868,7 @@ wheels = [
[[package]]
name = "praisonaiagents"
version = "0.0.62"
version = "0.0.65"
source = { editable = "." }
dependencies = [
{ name = "openai" },
Generated
+5 -5
View File
@@ -3060,7 +3060,7 @@ wheels = [
[[package]]
name = "praisonai"
version = "2.0.77"
version = "2.0.80"
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.62" },
{ name = "praisonaiagents", specifier = ">=0.0.65" },
{ 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.62"
version = "0.0.65"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "openai" },
{ name = "pydantic" },
{ name = "rich" },
]
sdist = { url = "https://files.pythonhosted.org/packages/26/44/528286f187d8be35839382251407a3b5ec7ecf5fc9b1fafd7e4197b436cb/praisonaiagents-0.0.62.tar.gz", hash = "sha256:d461553d7dc64441544a6ad92e6e446531f1be8e5cbb95261407540756b2cb8a", size = 104636 }
sdist = { url = "https://files.pythonhosted.org/packages/9e/58/6e07c4abf57d78be642f1517fe0692a003dfc253ad91a03c70521d246b5e/praisonaiagents-0.0.65.tar.gz", hash = "sha256:16627166f1b42bd8d21759fbd67015fff0b4730ca224b4a566cffe2b5bb770e8", size = 105128 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/42/34/c389ba1a9a45b0f7637b073e25717d2f9e0e6e727cc4946182fcf86e8c12/praisonaiagents-0.0.62-py3-none-any.whl", hash = "sha256:f6883ba12642bb3a7af277bfc1c0020276c3ac31bc251ed381f0388b3a61e73b", size = 123702 },
{ url = "https://files.pythonhosted.org/packages/04/02/e4f2ef3c008a407d3b945256d1513bf0159989055e9462c691265be3d294/praisonaiagents-0.0.65-py3-none-any.whl", hash = "sha256:f53e9c3ddf31c575dd5f65315db70b35487adb0f9ae908596e74ed315c12afc5", size = 124306 },
]
[[package]]