Compare commits

...
2 Commits
Author SHA1 Message Date
Mervin Praison d6a3bd1240 Merge pull request #604 from MervinPraison/develop
Update PraisonAI version to 2.2.28 across Dockerfiles and related files
2025-06-04 22:59:48 +01:00
MervinPraison 0a18e27f54 Update PraisonAI version to 2.2.28 across Dockerfiles and related files
- Updated the version of PraisonAI from 2.2.27 to 2.2.28 in Dockerfiles (Dockerfile, Dockerfile.chat, Dockerfile.dev, Dockerfile.ui).
- Modified the version in the README.md and pyproject.toml files to reflect the new version.
- Adjusted the deploy.py script to install the updated version of PraisonAI.
- Ensured consistency across all relevant files for seamless integration.
2025-06-04 22:59:30 +01:00
18 changed files with 5174 additions and 4799 deletions

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
flask \
"praisonai>=2.2.27" \
"praisonai>=2.2.28" \
"praisonai[api]" \
gunicorn \
markdown
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=2.2.27" \
"praisonai>=2.2.28" \
"praisonai[chat]" \
"embedchain[github,youtube]"
+1 -1
View File
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=2.2.27" \
"praisonai>=2.2.28" \
"praisonai[ui]" \
"praisonai[chat]" \
"praisonai[realtime]" \
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=2.2.27" \
"praisonai>=2.2.28" \
"praisonai[ui]" \
"praisonai[crewai]"
+2 -2
View File
@@ -121,7 +121,7 @@ healthcheck:
## 📦 Package Versions
All Docker images use consistent, up-to-date versions:
- PraisonAI: `>=2.2.27`
- PraisonAI: `>=2.2.28`
- PraisonAI Agents: `>=0.0.92`
- Python: `3.11-slim`
@@ -218,7 +218,7 @@ docker-compose up -d
### Version Pinning
To use specific versions, update the Dockerfile:
```dockerfile
RUN pip install "praisonai==2.2.27" "praisonaiagents==0.0.92"
RUN pip install "praisonai==2.2.28" "praisonaiagents==0.0.92"
```
## 🌐 Production Deployment
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
import sys
import traceback
from praisonaiagents import Agent, MCP
def test_agent_direct():
"""Test gpt-4o-mini (agent.py path)"""
print("=" * 50)
print("TESTING: gpt-4o-mini (agent.py direct calls)")
print("=" * 50)
try:
agent = Agent(
instructions="""You are a helpful assistant that can break down complex problems.
Use the available tools when relevant to perform step-by-step analysis.""",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
print("✅ Agent created successfully")
print(f"✅ Agent LLM: {getattr(agent, 'llm', 'Not set')}")
print(f"✅ Agent using custom LLM: {getattr(agent, '_using_custom_llm', False)}")
result = agent.start("What are 3 steps to make coffee?")
print("✅ Agent execution completed successfully")
return True, result
except Exception as e:
print(f"❌ Error in agent direct: {e}")
traceback.print_exc()
return False, str(e)
def test_llm_class():
"""Test openai/gpt-4o-mini (llm.py path)"""
print("\n" + "=" * 50)
print("TESTING: openai/gpt-4o-mini (llm.py LiteLLM)")
print("=" * 50)
try:
agent = Agent(
instructions="""You are a helpful assistant that can break down complex problems.
Use the available tools when relevant to perform step-by-step analysis.""",
llm="openai/gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
print("✅ Agent created successfully")
print(f"✅ Agent LLM instance: {getattr(agent, 'llm_instance', 'Not set')}")
print(f"✅ Agent using custom LLM: {getattr(agent, '_using_custom_llm', False)}")
result = agent.start("What are 3 steps to make coffee?")
print("✅ Agent execution completed successfully")
return True, result
except Exception as e:
print(f"❌ Error in llm class: {e}")
traceback.print_exc()
return False, str(e)
if __name__ == "__main__":
print("🔍 DEBUGGING: Comparing both LLM approaches\n")
# Test agent direct
success1, result1 = test_agent_direct()
# Test LLM class
success2, result2 = test_llm_class()
print("\n" + "=" * 50)
print("FINAL RESULTS")
print("=" * 50)
if success1:
print("✅ gpt-4o-mini (agent.py) - SUCCESS")
else:
print("❌ gpt-4o-mini (agent.py) - FAILED")
print(f" Error: {result1}")
if success2:
print("✅ openai/gpt-4o-mini (llm.py) - SUCCESS")
else:
print("❌ openai/gpt-4o-mini (llm.py) - FAILED")
print(f" Error: {result2}")
if success1 and success2:
print("\n🎉 BOTH FORMATS WORK CORRECTLY!")
print("📝 The issue mentioned might be resolved or was a different problem.")
elif success1 and not success2:
print("\n⚠️ CONFIRMED: LLM class path has issues")
print("📝 Need to debug the LLM class implementation")
elif success2 and not success1:
print("\n⚠️ CONFIRMED: Agent direct path has issues")
print("📝 Need to debug the agent direct implementation")
else:
print("\n💥 BOTH PATHS FAILED - Something is fundamentally wrong")
+246 -146
View File
@@ -413,24 +413,30 @@ class LLM:
start_time = time.time()
reflection_count = 0
while True:
try:
if verbose:
display_text = prompt
if isinstance(prompt, list):
display_text = next((item["text"] for item in prompt if item["type"] == "text"), "")
if display_text and str(display_text).strip():
display_instruction(
f"Agent {agent_name} is processing prompt: {display_text}",
console=console,
agent_name=agent_name,
agent_role=agent_role,
agent_tools=agent_tools
)
# Display initial instruction once
if verbose:
display_text = prompt
if isinstance(prompt, list):
display_text = next((item["text"] for item in prompt if item["type"] == "text"), "")
if display_text and str(display_text).strip():
display_instruction(
f"Agent {agent_name} is processing prompt: {display_text}",
console=console,
agent_name=agent_name,
agent_role=agent_role,
agent_tools=agent_tools
)
# Sequential tool calling loop - similar to agent.py
max_iterations = 10 # Prevent infinite loops
iteration_count = 0
final_response_text = ""
while iteration_count < max_iterations:
try:
# Get response from LiteLLM
start_time = time.time()
current_time = time.time()
# If reasoning_steps is True, do a single non-streaming call
if reasoning_steps:
@@ -445,6 +451,7 @@ class LLM:
)
reasoning_content = resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
response_text = resp["choices"][0]["message"]["content"]
final_response = resp
# Optionally display reasoning if present
if verbose and reasoning_content:
@@ -452,7 +459,7 @@ class LLM:
original_prompt,
f"Reasoning:\n{reasoning_content}\n\nAnswer:\n{response_text}",
markdown=markdown,
generation_time=time.time() - start_time,
generation_time=time.time() - current_time,
console=console
)
else:
@@ -460,14 +467,14 @@ class LLM:
original_prompt,
response_text,
markdown=markdown,
generation_time=time.time() - start_time,
generation_time=time.time() - current_time,
console=console
)
# Otherwise do the existing streaming approach
else:
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
response_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
@@ -481,7 +488,7 @@ class LLM:
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
response_text += content
live.update(display_generating(response_text, start_time))
live.update(display_generating(response_text, current_time))
else:
# Non-verbose mode, just collect the response
response_text = ""
@@ -499,20 +506,20 @@ class LLM:
response_text = response_text.strip()
# Get final completion to check for tool calls
final_response = litellm.completion(
**self._build_completion_params(
messages=messages,
tools=formatted_tools,
temperature=temperature,
stream=False, # No streaming for tool call check
**kwargs
# Get final completion to check for tool calls
final_response = litellm.completion(
**self._build_completion_params(
messages=messages,
tools=formatted_tools,
temperature=temperature,
stream=False, # No streaming for tool call check
**kwargs
)
)
)
tool_calls = final_response["choices"][0]["message"].get("tool_calls")
# Handle tool calls
# Handle tool calls - Sequential tool calling logic
if tool_calls and execute_tool_fn:
# Convert tool_calls to a serializable format for all providers
serializable_tool_calls = []
@@ -535,6 +542,7 @@ class LLM:
"tool_calls": serializable_tool_calls
})
should_continue = False
for tool_call in tool_calls:
# Handle both object and dict access patterns
if isinstance(tool_call, dict):
@@ -574,6 +582,18 @@ class LLM:
"content": json.dumps(tool_result) if tool_result is not None else "Function returned an empty output"
})
# Check if we should continue (for tools like sequential thinking)
# This mimics the logic from agent.py lines 1004-1007
if function_name == "sequentialthinking" and arguments.get("nextThoughtNeeded", False):
should_continue = True
# If we should continue, increment iteration and continue loop
if should_continue:
iteration_count += 1
continue
# If we reach here, no more tool calls needed - get final response
# Make one more call to get the final summary response
# Special handling for Ollama models that don't automatically process tool results
if self.model and self.model.startswith("ollama/") and tool_result:
# For Ollama models, we need to explicitly ask the model to process the tool results
@@ -666,115 +686,141 @@ class LLM:
else:
# Get response after tool calls with streaming
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
response_text = ""
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
final_response_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
messages=messages,
tools=formatted_tools,
temperature=temperature,
stream=True
stream=True,
**kwargs
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
response_text += content
live.update(display_generating(response_text, start_time))
final_response_text += content
live.update(display_generating(final_response_text, current_time))
else:
response_text = ""
final_response_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
messages=messages,
tools=formatted_tools,
temperature=temperature,
stream=True
stream=True,
**kwargs
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
response_text = response_text.strip()
# Handle output formatting
if output_json or output_pydantic:
self.chat_history.append({"role": "user", "content": original_prompt})
self.chat_history.append({"role": "assistant", "content": response_text})
final_response_text += chunk.choices[0].delta.content
final_response_text = final_response_text.strip()
# Display final response
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
display_interaction(
original_prompt,
final_response_text,
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
return final_response_text
else:
# No tool calls, we're done with this iteration
break
except Exception as e:
logging.error(f"Error in LLM iteration {iteration_count}: {e}")
break
# End of while loop - return final response
if final_response_text:
return final_response_text
# No tool calls were made in this iteration, return the response
if verbose:
display_interaction(
original_prompt,
response_text,
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
response_text = response_text.strip()
# Handle output formatting
if output_json or output_pydantic:
self.chat_history.append({"role": "user", "content": original_prompt})
self.chat_history.append({"role": "assistant", "content": response_text})
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
if not self_reflect:
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
# Return reasoning content if reasoning_steps is True
if reasoning_steps and reasoning_content:
return reasoning_content
return response_text
if not self_reflect:
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
# Return reasoning content if reasoning_steps is True
if reasoning_steps and reasoning_content:
return reasoning_content
return response_text
# Handle self-reflection
reflection_prompt = f"""
# Handle self-reflection loop
while reflection_count < max_reflect:
# Handle self-reflection
reflection_prompt = f"""
Reflect on your previous response: '{response_text}'.
Identify any flaws, improvements, or actions.
Provide a "satisfactory" status ('yes' or 'no').
Output MUST be JSON with 'reflection' and 'satisfactory'.
"""
reflection_messages = messages + [
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt}
]
"""
reflection_messages = messages + [
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt}
]
# If reasoning_steps is True, do a single non-streaming call to capture reasoning
if reasoning_steps:
reflection_resp = litellm.completion(
**self._build_completion_params(
messages=reflection_messages,
temperature=temperature,
stream=False, # Force non-streaming
response_format={"type": "json_object"},
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
)
# If reasoning_steps is True, do a single non-streaming call to capture reasoning
if reasoning_steps:
reflection_resp = litellm.completion(
**self._build_completion_params(
messages=reflection_messages,
temperature=temperature,
stream=False, # Force non-streaming
response_format={"type": "json_object"},
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
)
# Grab reflection text and optional reasoning
reasoning_content = reflection_resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
reflection_text = reflection_resp["choices"][0]["message"]["content"]
)
# Grab reflection text and optional reasoning
reasoning_content = reflection_resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
reflection_text = reflection_resp["choices"][0]["message"]["content"]
# Optionally display reasoning if present
if verbose and reasoning_content:
display_interaction(
"Reflection reasoning:",
f"{reasoning_content}\n\nReflection result:\n{reflection_text}",
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
elif verbose:
display_interaction(
"Self-reflection (non-streaming):",
reflection_text,
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
else:
# Existing streaming approach
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
reflection_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
messages=reflection_messages,
temperature=temperature,
stream=True,
response_format={"type": "json_object"},
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
reflection_text += content
live.update(display_generating(reflection_text, start_time))
else:
# Optionally display reasoning if present
if verbose and reasoning_content:
display_interaction(
"Reflection reasoning:",
f"{reasoning_content}\n\nReflection result:\n{reflection_text}",
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
elif verbose:
display_interaction(
"Self-reflection (non-streaming):",
reflection_text,
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
else:
# Existing streaming approach
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
reflection_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
@@ -786,48 +832,102 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
reflection_text += chunk.choices[0].delta.content
try:
reflection_data = json.loads(reflection_text)
satisfactory = reflection_data.get("satisfactory", "no").lower() == "yes"
if verbose:
display_self_reflection(
f"Agent {agent_name} self reflection: reflection='{reflection_data['reflection']}' satisfactory='{reflection_data['satisfactory']}'",
console=console
content = chunk.choices[0].delta.content
reflection_text += content
live.update(display_generating(reflection_text, start_time))
else:
reflection_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
messages=reflection_messages,
temperature=temperature,
stream=True,
response_format={"type": "json_object"},
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
reflection_text += chunk.choices[0].delta.content
if satisfactory and reflection_count >= min_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
try:
reflection_data = json.loads(reflection_text)
satisfactory = reflection_data.get("satisfactory", "no").lower() == "yes"
if reflection_count >= max_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
if verbose:
display_self_reflection(
f"Agent {agent_name} self reflection: reflection='{reflection_data['reflection']}' satisfactory='{reflection_data['satisfactory']}'",
console=console
)
reflection_count += 1
messages.extend([
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt},
{"role": "assistant", "content": reflection_text},
{"role": "user", "content": "Now regenerate your response using the reflection you made"}
])
continue
if satisfactory and reflection_count >= min_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
except json.JSONDecodeError:
reflection_count += 1
if reflection_count >= max_reflect:
return response_text
continue
if reflection_count >= max_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
reflection_count += 1
messages.extend([
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt},
{"role": "assistant", "content": reflection_text},
{"role": "user", "content": "Now regenerate your response using the reflection you made"}
])
# Get new response after reflection
if verbose:
with Live(display_generating("", time.time()), console=console, refresh_per_second=4) as live:
response_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
messages=messages,
temperature=temperature,
stream=True,
**kwargs
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
response_text += content
live.update(display_generating(response_text, time.time()))
else:
response_text = ""
for chunk in litellm.completion(
**self._build_completion_params(
messages=messages,
temperature=temperature,
stream=True,
**kwargs
)
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
response_text = response_text.strip()
continue
except json.JSONDecodeError:
reflection_count += 1
if reflection_count >= max_reflect:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
continue
except Exception as e:
display_error(f"Error in LLM response: {str(e)}")
return None
# If we've exhausted reflection attempts
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
except Exception as error:
display_error(f"Error in get_response: {str(error)}")
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.0.98"
version = "0.0.99"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
requires-python = ">=3.10"
authors = [
+1 -1
View File
@@ -4,7 +4,7 @@ import os
sequential_agent = Agent(
instructions="""You are a helpful assistant that can break down complex problems.
Use the available tools when relevant to perform step-by-step analysis.""",
llm="openai/gpt-4o-mini",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
+11
View File
@@ -0,0 +1,11 @@
from praisonaiagents import Agent, MCP
import os
sequential_agent = Agent(
instructions="""You are a helpful assistant that can break down complex problems.
Use the available tools when relevant to perform step-by-step analysis.""",
llm="openai/gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
sequential_agent.start("Break down the process of making a cup of tea")
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
from praisonaiagents import Agent, MCP
import os
def test_agent_direct():
"""Test using gpt-4o-mini directly (agent.py path)"""
print("="*50)
print("Testing gpt-4o-mini (agent.py path)")
print("="*50)
agent = Agent(
instructions="You are a helpful assistant that can break down complex problems.",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
result = agent.start("What are 5 steps to make coffee?")
print("✅ Agent direct path completed successfully")
return result
def test_llm_class():
"""Test using openai/gpt-4o-mini (llm.py path)"""
print("\n" + "="*50)
print("Testing openai/gpt-4o-mini (llm.py path)")
print("="*50)
agent = Agent(
instructions="You are a helpful assistant that can break down complex problems.",
llm="openai/gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
result = agent.start("What are 5 steps to make coffee?")
print("✅ LLM class path completed successfully")
return result
if __name__ == "__main__":
try:
# Test both approaches
result1 = test_agent_direct()
result2 = test_llm_class()
print("\n" + "="*50)
print("SUMMARY")
print("="*50)
print("✅ Both formats work correctly!")
print("✅ gpt-4o-mini uses agent.py direct OpenAI calls")
print("✅ openai/gpt-4o-mini uses llm.py LiteLLM wrapper")
print("✅ Both support tool calling and MCP integration")
except Exception as e:
print(f"❌ Error occurred: {e}")
import traceback
traceback.print_exc()
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Test self-reflection functionality in both Agent and LLM classes"""
from praisonaiagents import Agent
from praisonaiagents.llm import LLM
def test_agent_self_reflection():
"""Test self-reflection in Agent class"""
print("=== Testing Agent Self-Reflection ===")
agent = Agent(
name="ReflectiveAgent",
instructions="You are a helpful assistant.",
llm="gpt-4o-mini",
self_reflect=True,
min_reflect=1,
max_reflect=3
)
response = agent.start("What is 2+2? Be brief.")
print(f"Agent Response: {response}")
print()
def test_llm_self_reflection():
"""Test self-reflection in LLM class directly"""
print("=== Testing LLM Self-Reflection ===")
llm = LLM(model="gpt-4o-mini")
response = llm.get_response(
prompt="What is 2+2? Be brief.",
system_prompt="You are a helpful assistant.",
self_reflect=True,
min_reflect=1,
max_reflect=3,
verbose=True
)
print(f"LLM Response: {response}")
print()
def test_llm_no_reflection():
"""Test LLM without self-reflection for comparison"""
print("=== Testing LLM Without Self-Reflection ===")
llm = LLM(model="gpt-4o-mini")
response = llm.get_response(
prompt="What is 2+2? Be brief.",
system_prompt="You are a helpful assistant.",
self_reflect=False,
verbose=True
)
print(f"LLM Response: {response}")
print()
if __name__ == "__main__":
# Test without reflection first
test_llm_no_reflection()
# Test with reflection
test_llm_self_reflection()
# Test agent reflection
test_agent_self_reflection()
@@ -0,0 +1,56 @@
#!/usr/bin/env python3
from praisonaiagents import Agent, MCP
import os
def test_agent_direct():
"""Test using gpt-4o-mini directly (agent.py path)"""
print("=" * 50)
print("Testing gpt-4o-mini (agent.py path)")
print("=" * 50)
agent = Agent(
instructions="You are a helpful assistant that can break down complex problems.",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
result = agent.start("What are 3 steps to make coffee?")
print("✅ Agent direct path completed successfully")
return result
def test_llm_class():
"""Test using openai/gpt-4o-mini (llm.py path)"""
print("\n" + "=" * 50)
print("Testing openai/gpt-4o-mini (llm.py path)")
print("=" * 50)
agent = Agent(
instructions="You are a helpful assistant that can break down complex problems.",
llm="openai/gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
result = agent.start("What are 3 steps to make coffee?")
print("✅ LLM class path completed successfully")
return result
if __name__ == "__main__":
try:
# Test both approaches
result1 = test_agent_direct()
result2 = test_llm_class()
print("\n" + "=" * 50)
print("SUMMARY")
print("=" * 50)
print("✅ Both formats work correctly!")
print("✅ gpt-4o-mini uses agent.py direct OpenAI calls")
print("✅ openai/gpt-4o-mini uses llm.py LiteLLM wrapper")
print("✅ Both support sequential tool calling and MCP integration")
print("✅ Sequential thinking tool works properly in both modes")
except Exception as e:
print(f"❌ Error occurred: {e}")
import traceback
traceback.print_exc()
+2052 -2054
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -3,8 +3,8 @@ 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/v2.2.27.tar.gz"
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.27.tar.gz | shasum -a 256`.split.first
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.28.tar.gz"
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.28.tar.gz | shasum -a 256`.split.first
license "MIT"
depends_on "[email protected]"
+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.2.27 gunicorn markdown\n")
file.write("RUN pip install flask praisonai==2.2.28 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.2.27"
version = "2.2.28"
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.97",
"praisonaiagents>=0.0.99",
"python-dotenv>=0.19.0",
"instructor>=1.3.3",
"PyYAML>=6.0",
@@ -95,7 +95,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.15", "crewai"]
[tool.poetry]
name = "PraisonAI"
version = "2.2.27"
version = "2.2.28"
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 = ""
@@ -113,7 +113,7 @@ python = ">=3.10,<3.13"
rich = ">=13.7"
markdown = ">=3.5"
pyparsing = ">=3.0.0"
praisonaiagents = ">=0.0.97"
praisonaiagents = ">=0.0.99"
python-dotenv = ">=0.19.0"
instructor = ">=1.3.3"
PyYAML = ">=6.0"
+2582 -2584
View File
File diff suppressed because it is too large. Load diff