Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install flask praisonai==2.2.0 gunicorn markdown
RUN pip install flask praisonai==2.2.1 gunicorn markdown
EXPOSE 8080
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
2 changes: 1 addition & 1 deletion docker/Dockerfile.chat
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN pip install --no-cache-dir \
praisonaiagents>=0.0.4 \
praisonai_tools \
"praisonai==2.2.0" \
"praisonai==2.2.1" \
"praisonai[chat]" \
"embedchain[github,youtube]"

Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN pip install --no-cache-dir \
praisonaiagents>=0.0.4 \
praisonai_tools \
"praisonai==2.2.0" \
"praisonai==2.2.1" \
"praisonai[ui]" \
"praisonai[chat]" \
"praisonai[realtime]" \
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.ui
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN pip install --no-cache-dir \
praisonaiagents>=0.0.4 \
praisonai_tools \
"praisonai==2.2.0" \
"praisonai==2.2.1" \
"praisonai[ui]" \
"praisonai[crewai]"

Expand Down
2 changes: 1 addition & 1 deletion docs/api/praisonai/deploy.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ <h2 id="raises">Raises</h2>
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.2.0 gunicorn markdown\n&#34;)
file.write(&#34;RUN pip install flask praisonai==2.2.1 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;)

Expand Down
2 changes: 1 addition & 1 deletion docs/developers/local-development.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ WORKDIR /app

COPY . .

RUN pip install flask praisonai==2.2.0 watchdog
RUN pip install flask praisonai==2.2.1 watchdog

EXPOSE 5555

Expand Down
2 changes: 1 addition & 1 deletion docs/ui/chat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ To facilitate local development with live reload, you can use Docker. Follow the

COPY . .

RUN pip install flask praisonai==2.2.0 watchdog
RUN pip install flask praisonai==2.2.1 watchdog

EXPOSE 5555

Expand Down
2 changes: 1 addition & 1 deletion docs/ui/code.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ To facilitate local development with live reload, you can use Docker. Follow the

COPY . .

RUN pip install flask praisonai==2.2.0 watchdog
RUN pip install flask praisonai==2.2.1 watchdog

EXPOSE 5555

Expand Down
2 changes: 1 addition & 1 deletion praisonai/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.2.0 gunicorn markdown\n")
file.write("RUN pip install flask praisonai==2.2.1 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')

Expand Down
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "PraisonAI"
version = "2.2.0"
version = "2.2.1"
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 = ""
Expand All @@ -12,7 +12,7 @@ dependencies = [
"rich>=13.7",
"markdown>=3.5",
"pyparsing>=3.0.0",
"praisonaiagents>=0.0.83",
"praisonaiagents>=0.0.85",
"python-dotenv>=0.19.0",
"instructor>=1.3.3",
"PyYAML>=6.0",
Expand Down Expand Up @@ -89,7 +89,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.15", "crewai"]

[tool.poetry]
name = "PraisonAI"
version = "2.2.0"
version = "2.2.1"
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 = ""
Expand All @@ -107,7 +107,7 @@ python = ">=3.10,<3.13"
rich = ">=13.7"
markdown = ">=3.5"
pyparsing = ">=3.0.0"
praisonaiagents = ">=0.0.83"
praisonaiagents = ">=0.0.85"
python-dotenv = ">=0.19.0"
instructor = ">=1.3.3"
PyYAML = ">=6.0"
Expand Down
9 changes: 4 additions & 5 deletions src/praisonai-agents/mcp-sse.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from praisonaiagents import Agent, MCP

qa_agent = Agent(
instructions="""You are a Question Answering Agent.""",
llm="openai/gpt-4o-mini",
tools=MCP("http://localhost:8080/agents/sse")
tweet_agent = Agent(
instructions="""You are a Tweet Formatter Agent.""",
tools=MCP("http://localhost:8080/sse")
)
Comment on lines +3 to 6
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The llm="openai/gpt-4o-mini" parameter has been removed, and the agent name has changed. Previously, specifying the LLM this way (with a /) would engage the praisonaiagents.llm.LLM class, which serves as a wrapper around LiteLLM, for LLM interactions. With this parameter's removal, the Agent now defaults to using os.getenv('OPENAI_MODEL_NAME', 'gpt-4o') and interacts with the OpenAI API directly via the openai client, bypassing the LLM wrapper.

Could you clarify if this change in the example's LLM interaction mechanism (from LLM wrapper/LiteLLM to direct openai client) and model (from gpt-4o-mini to gpt-4o or an environment variable) is intentional? Also, why was the agent name changed from qa_agent to tweet_agent?

This change could lead to:

  1. Different LLM provider behavior or compatibility if users were relying on LiteLLM's broader support through the previous setup.
  2. Altered behavior or performance due to the change in model.
  3. Different cost implications for users running this example.
  4. Reduced clarity for users seeking to understand how to use the LLM wrapper for non-OpenAI models or advanced LiteLLM configurations through these examples.

If the intention is to simplify examples to use a direct OpenAI default, perhaps adding a comment in the example to explain this and to guide users on how to use the LLM class for other providers would be beneficial. Alternatively, if gpt-4o-mini via the LLM wrapper was specifically chosen for this example previously, it might be worth considering if that configuration should be retained or updated to reflect the new preferred method of specification.


qa_agent.start("AI in 2025")
tweet_agent.start("AI in Healthcare")
3 changes: 1 addition & 2 deletions src/praisonai-agents/openai-mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

search_agent = Agent(
instructions="""You help book apartments on Airbnb.""",
llm="openai/gpt-4o-mini",
tools=MCP("npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt")
)
Comment on lines 3 to 6
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the change in mcp-sse.py, the llm="openai/gpt-4o-mini" parameter has been removed. This means the agent, which previously would have used the praisonaiagents.llm.LLM class (wrapping LiteLLM) due to the "provider/model" format, will now default to using os.getenv('OPENAI_MODEL_NAME', 'gpt-4o') and interact directly with the OpenAI API via the openai client.

Is this shift in the example's LLM interaction pathway and the specific model used intentional?

This modification could impact:

  1. The example's behavior and performance characteristics.
  2. Cost for users running the example.
  3. The example's utility in demonstrating how to configure diverse LLMs or leverage LiteLLM features via the LLM wrapper.

Clarifying the rationale behind this change would be helpful. If the goal is to showcase a simpler default OpenAI setup, consider adding comments to guide users on more advanced configurations using the LLM class.


search_agent.start("I want to book an apartment in Paris for 2 nights. 03/28 - 03/30 for 2 adults")
search_agent.start("Search apartment in Paris for 2 nights. 07/28 - 07/30 for 2 adults")
15 changes: 8 additions & 7 deletions src/praisonai-agents/praisonaiagents/mcp/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
class MCPToolRunner(threading.Thread):
"""A dedicated thread for running MCP operations."""

def __init__(self, server_params):
def __init__(self, server_params, timeout=60):
super().__init__(daemon=True)
self.server_params = server_params
self.queue = queue.Queue()
self.result_queue = queue.Queue()
self.initialized = threading.Event()
self.tools = []
self.timeout = timeout
self.start()

def run(self):
Expand Down Expand Up @@ -74,9 +75,9 @@ async def _run_async(self):
def call_tool(self, tool_name, arguments):
"""Call an MCP tool and wait for the result."""
if not self.initialized.is_set():
self.initialized.wait(timeout=30)
self.initialized.wait(timeout=self.timeout)
if not self.initialized.is_set():
return "Error: MCP initialization timed out"
return f"Error: MCP initialization timed out after {self.timeout} seconds"
Comment on lines 79 to +80
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider adding a more descriptive error message that includes the specific tool that timed out, to aid in debugging.

return f"Error: MCP initialization timed out after {self.timeout} seconds for tool {tool_name}"

Style Guide References


# Put request in queue
self.queue.put((tool_name, arguments))
Expand Down Expand Up @@ -189,7 +190,7 @@ def __init__(self, command_or_string=None, args=None, *, command=None, timeout=6
if isinstance(command_or_string, str) and re.match(r'^https?://', command_or_string):
# Import the SSE client implementation
from .mcp_sse import SSEMCPClient
self.sse_client = SSEMCPClient(command_or_string, debug=debug)
self.sse_client = SSEMCPClient(command_or_string, debug=debug, timeout=timeout)
self._tools = list(self.sse_client.tools)
self.is_sse = True
self.is_npx = False
Expand All @@ -216,11 +217,11 @@ def __init__(self, command_or_string=None, args=None, *, command=None, timeout=6
args=arguments,
**kwargs
)
self.runner = MCPToolRunner(self.server_params)
self.runner = MCPToolRunner(self.server_params, timeout)

# Wait for initialization
if not self.runner.initialized.wait(timeout=30):
print("Warning: MCP initialization timed out")
if not self.runner.initialized.wait(timeout=self.timeout):
print(f"Warning: MCP initialization timed out after {self.timeout} seconds")

# Automatically detect if this is an NPX command
self.is_npx = cmd == 'npx' or (isinstance(cmd, str) and os.path.basename(cmd) == 'npx')
Expand Down
14 changes: 9 additions & 5 deletions src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ def get_event_loop():
class SSEMCPTool:
"""A wrapper for an MCP tool that can be used with praisonaiagents."""

def __init__(self, name: str, description: str, session: ClientSession, input_schema: Optional[Dict[str, Any]] = None):
def __init__(self, name: str, description: str, session: ClientSession, input_schema: Optional[Dict[str, Any]] = None, timeout: int = 60):
self.name = name
self.__name__ = name # Required for Agent to recognize it as a tool
self.__qualname__ = name # Required for Agent to recognize it as a tool
self.__doc__ = description # Required for Agent to recognize it as a tool
self.description = description
self.session = session
self.input_schema = input_schema or {}
self.timeout = timeout

# Create a signature based on input schema
params = []
Expand Down Expand Up @@ -66,7 +67,7 @@ def __call__(self, **kwargs):
future = asyncio.run_coroutine_threadsafe(self._async_call(**kwargs), loop)
try:
# Wait for the result with a timeout
return future.result(timeout=30)
return future.result(timeout=self.timeout)
except Exception as e:
logger.error(f"Error calling tool {self.name}: {e}")
return f"Error: {str(e)}"
Expand Down Expand Up @@ -102,16 +103,18 @@ def to_openai_tool(self):
class SSEMCPClient:
"""A client for connecting to an MCP server over SSE."""

def __init__(self, server_url: str, debug: bool = False):
def __init__(self, server_url: str, debug: bool = False, timeout: int = 60):
"""
Initialize an SSE MCP client.

Args:
server_url: The URL of the SSE MCP server
debug: Whether to enable debug logging
timeout: Timeout in seconds for operations (default: 60)
"""
self.server_url = server_url
self.debug = debug
self.timeout = timeout
self.session = None
self.tools = []

Expand Down Expand Up @@ -139,7 +142,7 @@ def run_event_loop():

# Run the initialization in the event loop
future = asyncio.run_coroutine_threadsafe(self._async_initialize(), loop)
self.tools = future.result(timeout=30)
self.tools = future.result(timeout=self.timeout)

async def _async_initialize(self):
"""Asynchronously initialize the connection and tools."""
Expand Down Expand Up @@ -169,7 +172,8 @@ async def _async_initialize(self):
name=tool.name,
description=tool.description if hasattr(tool, 'description') else f"Call the {tool.name} tool",
session=self.session,
input_schema=input_schema
input_schema=input_schema,
timeout=self.timeout
)
tools.append(wrapper)

Expand Down
2 changes: 1 addition & 1 deletion src/praisonai-agents/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "praisonaiagents"
version = "0.0.83"
version = "0.0.85"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
authors = [
{ name="Mervin Praison" }
Expand Down
2 changes: 1 addition & 1 deletion src/praisonai-agents/simple-mcp-server.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from praisonaiagents import Agent

agent = Agent(name="TweetAgent", instructions="Create a Tweet based on the topic provided")
agent = Agent(instructions="Create a Tweet")
agent.launch(port=8080, protocol="mcp")
2 changes: 1 addition & 1 deletion src/praisonai-agents/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading