mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-09 03:39:37 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faa014b8b0 | ||
|
|
6d454d0c6e | ||
|
|
0ec3fe3510 | ||
|
|
707888cdf9 |
No files matched your search
@@ -0,0 +1,19 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
llm_config = {
|
||||
"model": "deepseek/deepseek-reasoner",
|
||||
"max_tokens": 1
|
||||
}
|
||||
|
||||
reasoning_agent = Agent(role="Helpful Assistant", llm=llm_config, reasoning_steps=True)
|
||||
small_agent = Agent(role="Helpful Assistant", llm="openai/gpt-3.5-turbo")
|
||||
|
||||
reasoning_task = Task(description="How many r's in the word 'Strawberry'?", agent=reasoning_agent)
|
||||
small_task = Task(description="With the provided reasoning tell me how many r's in the word 'Strawberry'?", agent=small_agent)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[reasoning_agent, small_agent],
|
||||
tasks=[reasoning_task, small_task]
|
||||
)
|
||||
|
||||
agents.start()
|
||||
@@ -0,0 +1,14 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
reasoning_agent = Agent(role="Helpful Assistant", reasoning_steps=True, llm="deepseek/deepseek-reasoner")
|
||||
small_agent = Agent(role="Helpful Assistant", llm="openai/gpt-3.5-turbo")
|
||||
|
||||
reasoning_task = Task(description="How many r's in the word 'Strawberry'?", agent=reasoning_agent)
|
||||
small_task = Task(description="With the provided reasoning tell me how many r's in the word 'Strawberry'?", agent=small_agent)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[reasoning_agent, small_agent],
|
||||
tasks=[reasoning_task, small_task]
|
||||
)
|
||||
|
||||
agents.start()
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,30 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from langchain_community.tools import YouTubeSearchTool
|
||||
from langchain_community.utilities import WikipediaAPIWrapper
|
||||
|
||||
# Create an agent with both tools
|
||||
agent = Agent(
|
||||
name="SearchAgent",
|
||||
role="Research Assistant",
|
||||
goal="Search for information from multiple sources",
|
||||
backstory="I am an AI assistant that can search YouTube and Wikipedia.",
|
||||
tools=[YouTubeSearchTool, WikipediaAPIWrapper],
|
||||
llm="openai/gpt-4o-mini"
|
||||
)
|
||||
|
||||
# Create tasks to demonstrate both tools
|
||||
task = Task(
|
||||
name="search_task",
|
||||
description="Search for information about 'AI advancements' on both YouTube and Wikipedia",
|
||||
expected_output="Combined information from YouTube videos and Wikipedia articles",
|
||||
agent=agent
|
||||
)
|
||||
|
||||
# Create and start the workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agents.start()
|
||||
@@ -97,36 +97,79 @@ def process_stream_chunks(chunks):
|
||||
|
||||
content_list = []
|
||||
reasoning_list = []
|
||||
tool_calls = []
|
||||
current_tool_call = None
|
||||
|
||||
# First pass: Get initial tool call data
|
||||
for chunk in chunks:
|
||||
if not hasattr(chunk, "choices") or not chunk.choices:
|
||||
continue
|
||||
|
||||
# Track usage from each chunk
|
||||
if hasattr(chunk, "usage"):
|
||||
completion_tokens += getattr(chunk.usage, "completion_tokens", 0)
|
||||
prompt_tokens += getattr(chunk.usage, "prompt_tokens", 0)
|
||||
|
||||
delta = getattr(chunk.choices[0], "delta", None)
|
||||
if not delta:
|
||||
continue
|
||||
|
||||
|
||||
# Handle content and reasoning
|
||||
if hasattr(delta, "content") and delta.content:
|
||||
content_list.append(delta.content)
|
||||
if hasattr(delta, "reasoning_content") and delta.reasoning_content:
|
||||
reasoning_list.append(delta.reasoning_content)
|
||||
|
||||
# Handle tool calls
|
||||
if hasattr(delta, "tool_calls") and delta.tool_calls:
|
||||
for tool_call_delta in delta.tool_calls:
|
||||
if tool_call_delta.index is not None and tool_call_delta.id:
|
||||
# Found the initial tool call
|
||||
current_tool_call = {
|
||||
"id": tool_call_delta.id,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": tool_call_delta.function.name,
|
||||
"arguments": ""
|
||||
}
|
||||
}
|
||||
while len(tool_calls) <= tool_call_delta.index:
|
||||
tool_calls.append(None)
|
||||
tool_calls[tool_call_delta.index] = current_tool_call
|
||||
current_tool_call = tool_calls[tool_call_delta.index]
|
||||
elif current_tool_call is not None and hasattr(tool_call_delta.function, "arguments"):
|
||||
if tool_call_delta.function.arguments:
|
||||
current_tool_call["function"]["arguments"] += tool_call_delta.function.arguments
|
||||
|
||||
# Remove any None values and empty tool calls
|
||||
tool_calls = [tc for tc in tool_calls if tc and tc["id"] and tc["function"]["name"]]
|
||||
|
||||
combined_content = "".join(content_list) if content_list else ""
|
||||
combined_reasoning = "".join(reasoning_list) if reasoning_list else None
|
||||
finish_reason = getattr(last_chunk.choices[0], "finish_reason", None) if hasattr(last_chunk, "choices") and last_chunk.choices else None
|
||||
|
||||
# Create ToolCall objects
|
||||
processed_tool_calls = []
|
||||
if tool_calls:
|
||||
try:
|
||||
from openai.types.chat import ChatCompletionMessageToolCall
|
||||
for tc in tool_calls:
|
||||
tool_call = ChatCompletionMessageToolCall(
|
||||
id=tc["id"],
|
||||
type=tc["type"],
|
||||
function={
|
||||
"name": tc["function"]["name"],
|
||||
"arguments": tc["function"]["arguments"]
|
||||
}
|
||||
)
|
||||
processed_tool_calls.append(tool_call)
|
||||
except Exception as e:
|
||||
print(f"Error processing tool call: {e}")
|
||||
|
||||
message = ChatCompletionMessage(
|
||||
content=combined_content,
|
||||
reasoning_content=combined_reasoning
|
||||
role="assistant",
|
||||
reasoning_content=combined_reasoning,
|
||||
tool_calls=processed_tool_calls if processed_tool_calls else None
|
||||
)
|
||||
|
||||
choice = Choice(
|
||||
finish_reason=finish_reason,
|
||||
finish_reason=finish_reason or "tool_calls" if processed_tool_calls else None,
|
||||
index=0,
|
||||
message=message
|
||||
)
|
||||
@@ -528,6 +571,53 @@ Your Goal: {self.goal}
|
||||
def __str__(self):
|
||||
return f"Agent(name='{self.name}', role='{self.role}', goal='{self.goal}')"
|
||||
|
||||
def _process_stream_response(self, messages, temperature, start_time, formatted_tools=None, reasoning_steps=False):
|
||||
"""Process streaming response and return final response"""
|
||||
try:
|
||||
# Create the response stream
|
||||
response_stream = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools if formatted_tools else None,
|
||||
stream=True
|
||||
)
|
||||
|
||||
full_response_text = ""
|
||||
reasoning_content = ""
|
||||
chunks = []
|
||||
|
||||
# Create Live display with proper configuration
|
||||
with Live(
|
||||
display_generating("", start_time),
|
||||
console=self.console,
|
||||
refresh_per_second=4,
|
||||
transient=True,
|
||||
vertical_overflow="ellipsis",
|
||||
auto_refresh=True
|
||||
) as live:
|
||||
for chunk in response_stream:
|
||||
chunks.append(chunk)
|
||||
if chunk.choices[0].delta.content:
|
||||
full_response_text += chunk.choices[0].delta.content
|
||||
live.update(display_generating(full_response_text, start_time))
|
||||
|
||||
# Update live display with reasoning content if enabled
|
||||
if reasoning_steps and hasattr(chunk.choices[0].delta, "reasoning_content"):
|
||||
rc = chunk.choices[0].delta.reasoning_content
|
||||
if rc:
|
||||
reasoning_content += rc
|
||||
live.update(display_generating(f"{full_response_text}\n[Reasoning: {reasoning_content}]", start_time))
|
||||
|
||||
# Clear the last generating display with a blank line
|
||||
self.console.print()
|
||||
final_response = process_stream_chunks(chunks)
|
||||
return final_response
|
||||
|
||||
except Exception as e:
|
||||
display_error(f"Error in stream processing: {e}")
|
||||
return None
|
||||
|
||||
def _chat_completion(self, messages, temperature=0.2, tools=None, stream=True, reasoning_steps=False):
|
||||
start_time = time.time()
|
||||
logging.debug(f"{self.name} sending messages to LLM: {messages}")
|
||||
@@ -554,20 +644,31 @@ Your Goal: {self.goal}
|
||||
logging.warning(f"Tool {tool} not recognized")
|
||||
|
||||
try:
|
||||
initial_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools if formatted_tools else None,
|
||||
stream=False
|
||||
)
|
||||
if stream:
|
||||
# Process as streaming response with formatted tools
|
||||
final_response = self._process_stream_response(
|
||||
messages,
|
||||
temperature,
|
||||
start_time,
|
||||
formatted_tools=formatted_tools if formatted_tools else None,
|
||||
reasoning_steps=reasoning_steps
|
||||
)
|
||||
else:
|
||||
# Process as regular non-streaming response
|
||||
final_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools if formatted_tools else None,
|
||||
stream=False
|
||||
)
|
||||
|
||||
tool_calls = getattr(initial_response.choices[0].message, 'tool_calls', None)
|
||||
tool_calls = getattr(final_response.choices[0].message, 'tool_calls', None)
|
||||
|
||||
if tool_calls:
|
||||
messages.append({
|
||||
"role": "assistant",
|
||||
"content": initial_response.choices[0].message.content,
|
||||
"role": "assistant",
|
||||
"content": final_response.choices[0].message.content,
|
||||
"tool_calls": tool_calls
|
||||
})
|
||||
|
||||
@@ -590,55 +691,24 @@ Your Goal: {self.goal}
|
||||
"content": results_str
|
||||
})
|
||||
|
||||
if stream:
|
||||
response_stream = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=True
|
||||
)
|
||||
full_response_text = ""
|
||||
reasoning_content = ""
|
||||
chunks = []
|
||||
|
||||
# Create Live display with proper configuration
|
||||
with Live(
|
||||
display_generating("", start_time),
|
||||
console=self.console,
|
||||
refresh_per_second=4,
|
||||
transient=True,
|
||||
vertical_overflow="ellipsis",
|
||||
auto_refresh=True
|
||||
) as live:
|
||||
for chunk in response_stream:
|
||||
chunks.append(chunk)
|
||||
if chunk.choices[0].delta.content:
|
||||
full_response_text += chunk.choices[0].delta.content
|
||||
live.update(display_generating(full_response_text, start_time))
|
||||
|
||||
# Update live display with reasoning content if enabled
|
||||
if reasoning_steps and hasattr(chunk.choices[0].delta, "reasoning_content"):
|
||||
rc = chunk.choices[0].delta.reasoning_content
|
||||
if rc:
|
||||
reasoning_content += rc
|
||||
live.update(display_generating(f"{full_response_text}\n[Reasoning: {reasoning_content}]", start_time))
|
||||
|
||||
# Clear the last generating display with a blank line
|
||||
self.console.print()
|
||||
|
||||
final_response = process_stream_chunks(chunks)
|
||||
return final_response
|
||||
else:
|
||||
if tool_calls:
|
||||
# Get final response after tool calls
|
||||
if stream:
|
||||
final_response = self._process_stream_response(
|
||||
messages,
|
||||
temperature,
|
||||
start_time,
|
||||
formatted_tools=formatted_tools if formatted_tools else None,
|
||||
reasoning_steps=reasoning_steps
|
||||
)
|
||||
else:
|
||||
final_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False
|
||||
)
|
||||
return final_response
|
||||
else:
|
||||
return initial_response
|
||||
|
||||
return final_response
|
||||
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
@@ -758,8 +828,7 @@ Your Goal: {self.goal}
|
||||
|
||||
tool_calls = getattr(response.choices[0].message, 'tool_calls', None)
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
if tool_calls:
|
||||
if tool_calls: ## TODO: Most likely this tool call is already called in _chat_completion, so maybe we can remove this.
|
||||
messages.append({
|
||||
"role": "assistant",
|
||||
"content": response_text,
|
||||
@@ -988,48 +1057,48 @@ Your Goal: {self.goal}
|
||||
)
|
||||
|
||||
# Format tools if provided
|
||||
formatted_tools = []
|
||||
if tools:
|
||||
for tool in tools:
|
||||
if isinstance(tool, str):
|
||||
tool_def = self._generate_tool_definition(tool)
|
||||
if tool_def:
|
||||
formatted_tools.append(tool_def)
|
||||
elif isinstance(tool, dict):
|
||||
formatted_tools.append(tool)
|
||||
elif hasattr(tool, "to_openai_tool"):
|
||||
formatted_tools.append(tool.to_openai_tool())
|
||||
elif callable(tool):
|
||||
formatted_tools.append(self._generate_tool_definition(tool.__name__))
|
||||
formatted_tools = []
|
||||
if tools:
|
||||
for tool in tools:
|
||||
if isinstance(tool, str):
|
||||
tool_def = self._generate_tool_definition(tool)
|
||||
if tool_def:
|
||||
formatted_tools.append(tool_def)
|
||||
elif isinstance(tool, dict):
|
||||
formatted_tools.append(tool)
|
||||
elif hasattr(tool, "to_openai_tool"):
|
||||
formatted_tools.append(tool.to_openai_tool())
|
||||
elif callable(tool):
|
||||
formatted_tools.append(self._generate_tool_definition(tool.__name__))
|
||||
|
||||
# Create async OpenAI client
|
||||
async_client = AsyncOpenAI()
|
||||
# Create async OpenAI client
|
||||
async_client = AsyncOpenAI()
|
||||
|
||||
# Make the API call based on the type of request
|
||||
if tools:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools
|
||||
)
|
||||
return await self._achat_completion(response, tools)
|
||||
elif output_json or output_pydantic:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
# Return the raw response
|
||||
return response.choices[0].message.content
|
||||
else:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature
|
||||
)
|
||||
return response.choices[0].message.content
|
||||
# Make the API call based on the type of request
|
||||
if tools:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools
|
||||
)
|
||||
return await self._achat_completion(response, tools)
|
||||
elif output_json or output_pydantic:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
# Return the raw response
|
||||
return response.choices[0].message.content
|
||||
else:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature
|
||||
)
|
||||
return response.choices[0].message.content
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
return None
|
||||
|
||||
@@ -17,6 +17,8 @@ from ..main import (
|
||||
from rich.console import Console
|
||||
from rich.live import Live
|
||||
|
||||
# TODO: Include in-build tool calling in LLM class
|
||||
# TODO: Restructure so that duplicate calls are not made (Sync with agent.py)
|
||||
class LLMContextLengthExceededException(Exception):
|
||||
"""Raised when LLM context length is exceeded"""
|
||||
def __init__(self, message: str):
|
||||
@@ -178,7 +180,8 @@ class LLM:
|
||||
"""Enhanced get_response with all OpenAI-like features"""
|
||||
try:
|
||||
import litellm
|
||||
reasoning_steps = kwargs.get('reasoning_steps', self.reasoning_steps)
|
||||
# This below **kwargs** is passed to .completion() directly. so reasoning_steps has to be popped. OR find alternate best way of handling this.
|
||||
reasoning_steps = kwargs.pop('reasoning_steps', self.reasoning_steps)
|
||||
# Disable litellm debug messages
|
||||
litellm.set_verbose = False
|
||||
|
||||
@@ -240,7 +243,7 @@ class LLM:
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False, # force non-streaming
|
||||
**kwargs
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
reasoning_content = resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
|
||||
response_text = resp["choices"][0]["message"]["content"]
|
||||
@@ -344,7 +347,7 @@ class LLM:
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False, # force non-streaming
|
||||
**kwargs
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
reasoning_content = resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
|
||||
response_text = resp["choices"][0]["message"]["content"]
|
||||
@@ -435,7 +438,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=False, # Force non-streaming
|
||||
response_format={"type": "json_object"},
|
||||
**kwargs
|
||||
**{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")
|
||||
@@ -469,7 +472,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
response_format={"type": "json_object"},
|
||||
**kwargs
|
||||
**{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
|
||||
@@ -483,7 +486,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
response_format={"type": "json_object"},
|
||||
**kwargs
|
||||
**{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
|
||||
@@ -557,7 +560,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
"""Async version of get_response with identical functionality."""
|
||||
try:
|
||||
import litellm
|
||||
reasoning_steps = kwargs.get('reasoning_steps', self.reasoning_steps)
|
||||
reasoning_steps = kwargs.pop('reasoning_steps', self.reasoning_steps)
|
||||
litellm.set_verbose = False
|
||||
|
||||
# Build messages list
|
||||
@@ -669,7 +672,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False, # force non-streaming
|
||||
**kwargs
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
reasoning_content = resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
|
||||
response_text = resp["choices"][0]["message"]["content"]
|
||||
@@ -731,7 +734,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=False,
|
||||
tools=formatted_tools, # We safely pass tools here
|
||||
**kwargs
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
# handle tool_calls from tool_response as usual...
|
||||
tool_calls = tool_response.choices[0].message.get("tool_calls")
|
||||
@@ -777,7 +780,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=False, # force non-streaming
|
||||
tools=formatted_tools, # Include tools
|
||||
**kwargs
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
reasoning_content = resp["choices"][0]["message"].get("provider_specific_fields", {}).get("reasoning_content")
|
||||
response_text = resp["choices"][0]["message"]["content"]
|
||||
@@ -807,7 +810,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
tools=formatted_tools,
|
||||
**kwargs
|
||||
**{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
|
||||
@@ -821,7 +824,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
**kwargs
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta.content:
|
||||
response_text += chunk.choices[0].delta.content
|
||||
@@ -867,7 +870,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=False, # Force non-streaming
|
||||
response_format={"type": "json_object"},
|
||||
**kwargs
|
||||
**{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")
|
||||
@@ -901,7 +904,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
response_format={"type": "json_object"},
|
||||
**kwargs
|
||||
**{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
|
||||
@@ -915,7 +918,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
response_format={"type": "json_object"},
|
||||
**kwargs
|
||||
**{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
|
||||
|
||||
@@ -44,6 +44,8 @@ class Process:
|
||||
current_task = start_task
|
||||
visited_tasks = set()
|
||||
loop_data = {} # Store loop-specific data
|
||||
|
||||
# TODO: start task with loop feature is not available in aworkflow method
|
||||
|
||||
while current_task:
|
||||
current_iter += 1
|
||||
@@ -350,9 +352,10 @@ Provide a JSON with the structure:
|
||||
if row: # Skip empty rows
|
||||
task_desc = row[0] # Take first column
|
||||
row_task = Task(
|
||||
description=task_desc, # Keep full row as description
|
||||
description=f"{start_task.description}\n{task_desc}" if start_task.description else task_desc,
|
||||
agent=start_task.agent,
|
||||
name=task_desc, # Use first column as name
|
||||
name=f"{start_task.name}_{i+1}" if start_task.name else task_desc,
|
||||
expected_output=getattr(start_task, 'expected_output', None),
|
||||
is_start=(i == 0),
|
||||
task_type="task",
|
||||
condition={
|
||||
@@ -374,9 +377,10 @@ Provide a JSON with the structure:
|
||||
previous_task = None
|
||||
for i, line in enumerate(lines):
|
||||
row_task = Task(
|
||||
description=line.strip(),
|
||||
description=f"{start_task.description}\n{line.strip()}" if start_task.description else line.strip(),
|
||||
agent=start_task.agent,
|
||||
name=line.strip(),
|
||||
name=f"{start_task.name}_{i+1}" if start_task.name else line.strip(),
|
||||
expected_output=getattr(start_task, 'expected_output', None),
|
||||
is_start=(i == 0),
|
||||
task_type="task",
|
||||
condition={
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.53"
|
||||
version = "0.0.56"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
authors = [
|
||||
{ name="Mervin Praison" }
|
||||
|
||||
@@ -6,7 +6,8 @@ agent = Agent(
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Create the list of tasks to be looped through.",
|
||||
description="complete the task",
|
||||
expected_output="task completed",
|
||||
agent=agent,
|
||||
task_type="loop",
|
||||
input_file="tasks.csv"
|
||||
|
||||
Generated
+1
-1
@@ -1868,7 +1868,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.53"
|
||||
version = "0.0.56"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
|
||||
@@ -7,6 +7,7 @@ agent = Agent(
|
||||
self_reflect=True,
|
||||
min_reflect=3,
|
||||
max_reflect=5,
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
agent.start(
|
||||
"What is the history of AI?"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install flask praisonai==2.0.58 gunicorn markdown
|
||||
RUN pip install flask praisonai==2.0.59 gunicorn markdown
|
||||
EXPOSE 8080
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
|
||||
@@ -110,7 +110,7 @@ Loads environment variables from .env file or system and sets them.</p>
|
||||
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.58 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.59 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
+1
-1
@@ -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.58.tar.gz"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.59.tar.gz"
|
||||
sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum
|
||||
license "MIT"
|
||||
|
||||
|
||||
+1
-1
@@ -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.58 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.59 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.58"
|
||||
version = "2.0.59"
|
||||
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.53",
|
||||
"praisonaiagents>=0.0.56",
|
||||
"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.58"
|
||||
version = "2.0.59"
|
||||
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.53"
|
||||
praisonaiagents = ">=0.0.56"
|
||||
python-dotenv = ">=0.19.0"
|
||||
instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
|
||||
@@ -3060,7 +3060,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonai"
|
||||
version = "2.0.58"
|
||||
version = "2.0.59"
|
||||
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.53" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.56" },
|
||||
{ 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.53"
|
||||
version = "0.0.56"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "rich" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/48/7c/c8070c6eb7fcabe22aac9a6b92f72cfcd5a04d02e8f7bcff0e42f62eb31f/praisonaiagents-0.0.53.tar.gz", hash = "sha256:02a8220977776c8a1574b160f3e12b90ac98adc9b3925773e9867c117e10e6f9", size = 87386 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1f/d0/5b3ee6832c4797cb6dd47496485789e13113014d501856c2b5b286e7108c/praisonaiagents-0.0.56.tar.gz", hash = "sha256:148b6400403a7ad05b105084640e7140799e4e3bfb23a844bb79e10ea98bf859", size = 88236 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/56/9b/0f9f2b146877d5b830173981030c1acb82d10ce719b27af085900c2c4763/praisonaiagents-0.0.53-py3-none-any.whl", hash = "sha256:dd7a08cba8dc283136e7f94111f0ced95f172a8a3d9fcdf64dda6f4f1521d7ff", size = 105546 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/7e/1da42b51510d3bef28f4d450824d7d14fdd2358981adf7c5b8251e586526/praisonaiagents-0.0.56-py3-none-any.whl", hash = "sha256:b198c60a8909c39b2ced09e0c7cc1ad6224af15b8c743f6890ef3985fae4d036", size = 106340 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in new issue
Block a user