Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c460c9da60 | ||
|
|
656887c700 | ||
|
|
e0089cac41 | ||
|
|
bf5e069c7b | ||
|
|
94cf264b4c | ||
|
|
ab44fd4b27 | ||
|
|
7bad6cf7e9 | ||
|
|
4ffbe48c58 | ||
|
|
476eeb1184 | ||
|
|
550769017a | ||
|
|
cccd75ca75 | ||
|
|
395f8fb5ef | ||
|
|
e4893ad948 | ||
|
|
e717b625d2 | ||
|
|
84638ad759 | ||
|
|
626bc963f7 | ||
|
|
efa7110b38 | ||
|
|
539c10796c | ||
|
|
815becb6f2 | ||
|
|
87790695db | ||
|
|
00b25bb195 | ||
|
|
e46ca3248d | ||
|
|
04f6beaa56 | ||
|
|
3d99326192 | ||
|
|
70ced6acbb | ||
|
|
dc14c06e41 | ||
|
|
deb1148c8a | ||
|
|
3d6d7c0b02 | ||
|
|
1a5a25073e | ||
|
|
7b743e6982 | ||
|
|
77a3512779 | ||
|
|
2a4ec38077 | ||
|
|
25f59b5c26 | ||
|
|
7596ed252d | ||
|
|
14bea558fb | ||
|
|
b5b3d8abd0 |
No files matched your search
@@ -1,6 +1,6 @@
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install flask praisonai==2.0.20 gunicorn markdown
|
||||
RUN pip install flask praisonai==2.0.32 gunicorn markdown
|
||||
EXPOSE 8080
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
|
||||
@@ -22,17 +22,30 @@
|
||||
|
||||
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.
|
||||
|
||||
<div align="center">
|
||||
<a href="https://docs.praison.ai">
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/📚_Documentation-Visit_docs.praison.ai-blue?style=for-the-badge&logo=bookstack&logoColor=white" alt="Documentation" />
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Key Features
|
||||
|
||||
- 🤖 Automated AI Agents Creation
|
||||
- 🔄 Self Reflection AI Agents
|
||||
- 🧠 Reasoning AI Agents
|
||||
- 👁️ Multi Modal AI Agents
|
||||
- 🤝 Multi Agent Collaboration
|
||||
- ⚡ AI Agent Workflow
|
||||
- 🔄 Use CrewAI or AutoGen Framework
|
||||
- 💯 100+ LLM Support
|
||||
- 💻 Chat with ENTIRE Codebase
|
||||
- 🖥️ Interactive UIs
|
||||
- 🎨 Interactive UIs
|
||||
- 📄 YAML-based Configuration
|
||||
- 🛠️ Custom Tool Integration
|
||||
- 🔍 Internet Search Capability (using Crawl4AI and Tavily)
|
||||
- 👁️ Vision Language Model (VLM) Support
|
||||
- 🖼️ Vision Language Model (VLM) Support
|
||||
- 🎙️ Real-time Voice Interaction
|
||||
|
||||
## Using No Code
|
||||
|
||||
@@ -7,12 +7,8 @@ roles:
|
||||
information.
|
||||
goal: Gather information about Mars and cats
|
||||
role: Researcher
|
||||
llm:
|
||||
model: "gpt-4o"
|
||||
reflect_llm:
|
||||
model: "gpt-4o"
|
||||
min_reflect: 2
|
||||
max_reflect: 4
|
||||
min_reflect: 1
|
||||
max_reflect: 2
|
||||
tasks:
|
||||
research_task:
|
||||
description: Research about Mars, its environment, and the feasibility of
|
||||
@@ -25,8 +21,6 @@ roles:
|
||||
stories.
|
||||
goal: Create a story concept for a movie about a cat in Mars
|
||||
role: Narrative Designer
|
||||
llm:
|
||||
model: "gpt-4o"
|
||||
tasks:
|
||||
story_concept_development:
|
||||
description: Use the research findings to craft a unique story concept for
|
||||
@@ -39,8 +33,6 @@ roles:
|
||||
scripts.
|
||||
goal: Write a movie script about a cat in Mars
|
||||
role: Scriptwriter
|
||||
llm:
|
||||
model: "gpt-4o"
|
||||
tasks:
|
||||
scriptwriting_task:
|
||||
description: Turn the story concept into a production-ready movie script,
|
||||
@@ -48,4 +40,4 @@ roles:
|
||||
expected_output: Final movie script with dialogue and scene details.
|
||||
tools:
|
||||
- ''
|
||||
dependencies: []
|
||||
dependencies: []
|
||||
@@ -0,0 +1,233 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from praisonaiagents.main import (
|
||||
display_error,
|
||||
display_interaction,
|
||||
display_tool_call,
|
||||
display_instruction,
|
||||
error_logs,
|
||||
Console
|
||||
)
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
console = Console()
|
||||
|
||||
# 1. Define output model for structured results
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
# 2. Define both sync and async tools
|
||||
def sync_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Synchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
list: Search results
|
||||
"""
|
||||
display_tool_call(f"Running sync search for: {query}", console)
|
||||
time.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error during sync search: {e}"
|
||||
display_error(error_msg, console)
|
||||
error_logs.append(error_msg)
|
||||
return []
|
||||
|
||||
async def async_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Asynchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
list: Search results
|
||||
"""
|
||||
display_tool_call(f"Running async search for: {query}", console)
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error during async search: {e}"
|
||||
display_error(error_msg, console)
|
||||
error_logs.append(error_msg)
|
||||
return []
|
||||
|
||||
# 3. Define both sync and async callbacks
|
||||
def sync_callback(output: TaskOutput):
|
||||
display_interaction("Sync Callback", f"Processing output: {output.raw[:100]}...", markdown=True, console=console)
|
||||
time.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
display_tool_call(f"Processed JSON result: {output.json_dict}", console)
|
||||
elif output.output_format == "Pydantic":
|
||||
display_tool_call(f"Processed Pydantic result: {output.pydantic}", console)
|
||||
|
||||
async def async_callback(output: TaskOutput):
|
||||
display_interaction("Async Callback", f"Processing output: {output.raw[:100]}...", markdown=True, console=console)
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
display_tool_call(f"Processed JSON result: {output.json_dict}", console)
|
||||
elif output.output_format == "Pydantic":
|
||||
display_tool_call(f"Processed Pydantic result: {output.pydantic}", console)
|
||||
|
||||
# 4. Create agents with different tools
|
||||
sync_agent = Agent(
|
||||
name="SyncAgent",
|
||||
role="Synchronous Search Specialist",
|
||||
goal="Perform synchronous searches and return structured results",
|
||||
backstory="Expert in sync operations and data organization",
|
||||
tools=[sync_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
async_agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Asynchronous Search Specialist",
|
||||
goal="Perform asynchronous searches and return structured results",
|
||||
backstory="Expert in async operations and data organization",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 5. Create tasks with different configurations
|
||||
sync_task = Task(
|
||||
name="sync_search",
|
||||
description="Search for 'Python programming' using sync tool and return structured results",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=sync_agent,
|
||||
async_execution=False,
|
||||
callback=sync_callback,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="Search for 'Async programming' using async tool and return structured results",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
# 6. Create workflow tasks
|
||||
workflow_sync_task = Task(
|
||||
name="workflow_sync",
|
||||
description="Workflow sync search for 'AI trends' with structured output",
|
||||
expected_output="SearchResult model with AI trends data",
|
||||
agent=sync_agent,
|
||||
async_execution=False,
|
||||
is_start=True,
|
||||
next_tasks=["workflow_async"],
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
workflow_async_task = Task(
|
||||
name="workflow_async",
|
||||
description="Workflow async search for 'Future of AI' with structured output",
|
||||
expected_output="SearchResult model with Future of AI data",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
# 7. Example usage functions
|
||||
def run_sync_example():
|
||||
"""Run synchronous example"""
|
||||
display_instruction("\nRunning Synchronous Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent],
|
||||
tasks=[sync_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = agents.start()
|
||||
display_interaction("Sync Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
async def run_async_example():
|
||||
"""Run asynchronous example"""
|
||||
display_instruction("\nRunning Asynchronous Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
display_interaction("Async Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
async def run_mixed_example():
|
||||
"""Run mixed sync/async example"""
|
||||
display_instruction("\nRunning Mixed Sync/Async Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent, async_agent],
|
||||
tasks=[sync_task, async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
display_interaction("Mixed Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
async def run_workflow_example():
|
||||
"""Run workflow example with both sync and async tasks"""
|
||||
display_instruction("\nRunning Workflow Example...", console)
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent, async_agent],
|
||||
tasks=[workflow_sync_task, workflow_async_task],
|
||||
verbose=1,
|
||||
process="workflow"
|
||||
)
|
||||
result = await agents.astart()
|
||||
display_interaction("Workflow Example", f"Result: {result}", markdown=True, console=console)
|
||||
|
||||
# 8. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
display_instruction("Starting PraisonAI Agents Examples...", console)
|
||||
|
||||
try:
|
||||
# Run sync example in a separate thread to not block the event loop
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, run_sync_example)
|
||||
|
||||
# Run async examples
|
||||
await run_async_example()
|
||||
await run_mixed_example()
|
||||
await run_workflow_example()
|
||||
|
||||
if error_logs:
|
||||
display_error("\nErrors encountered during execution:", console)
|
||||
for error in error_logs:
|
||||
display_error(error, console)
|
||||
except Exception as e:
|
||||
display_error(f"Error in main execution: {e}", console)
|
||||
error_logs.append(str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,152 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
# 1. Define output model for structured results
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
# 2. Define async tool
|
||||
async def async_search_tool(query: str) -> Dict:
|
||||
"""Perform asynchronous search and return structured results."""
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
|
||||
return {
|
||||
"query": query,
|
||||
"results": results,
|
||||
"total_results": len(results)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error during async search: {e}")
|
||||
return {
|
||||
"query": query,
|
||||
"results": [],
|
||||
"total_results": 0
|
||||
}
|
||||
|
||||
# 3. Define async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
print(f"Processed JSON result: {output.json_dict}")
|
||||
elif output.output_format == "Pydantic":
|
||||
print(f"Processed Pydantic result: {output.pydantic}")
|
||||
|
||||
# 4. Create specialized agents
|
||||
async_agent = Agent(
|
||||
name="AsyncSearchAgent",
|
||||
role="Search Specialist",
|
||||
goal="Perform fast parallel searches with structured results",
|
||||
backstory="Expert in efficient data retrieval and parallel search operations",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
summary_agent = Agent(
|
||||
name="SummaryAgent",
|
||||
role="Research Synthesizer",
|
||||
goal="Create concise summaries from multiple search results",
|
||||
backstory="Expert in analyzing and synthesizing information from multiple sources",
|
||||
self_reflect=True,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 5. Create async tasks
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="Search for 'Async programming' and return results in JSON format with query, results array, and total_results count.",
|
||||
expected_output="SearchResult model with structured data",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
)
|
||||
|
||||
async def run_parallel_tasks():
|
||||
"""Run multiple async tasks in parallel"""
|
||||
print("\nRunning Parallel Async Tasks...")
|
||||
|
||||
# Define different search topics
|
||||
search_topics = [
|
||||
"Latest AI Developments 2024",
|
||||
"Machine Learning Best Practices",
|
||||
"Neural Networks Architecture"
|
||||
]
|
||||
|
||||
# Create tasks for different topics
|
||||
parallel_tasks = [
|
||||
Task(
|
||||
name=f"search_task_{i}",
|
||||
description=f"Search for '{topic}' and return structured results with query details and findings.",
|
||||
expected_output="SearchResult model with search data",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
) for i, topic in enumerate(search_topics)
|
||||
]
|
||||
|
||||
# Create summarization task
|
||||
summary_task = Task(
|
||||
name="summary_task",
|
||||
description="Analyze all search results and create a concise summary highlighting key findings, patterns, and implications.",
|
||||
expected_output="Structured summary with key findings and insights",
|
||||
agent=summary_agent,
|
||||
async_execution=False,
|
||||
callback=async_callback,
|
||||
context=parallel_tasks
|
||||
)
|
||||
|
||||
# Create a single PraisonAIAgents instance with both agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent, summary_agent],
|
||||
tasks=parallel_tasks + [summary_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Run all tasks
|
||||
results = await agents.astart()
|
||||
print(f"Tasks Results: {results}")
|
||||
|
||||
# Return results in a serializable format
|
||||
return {
|
||||
"search_results": {
|
||||
"task_status": {k: v for k, v in results["task_status"].items() if k != summary_task.id},
|
||||
"task_results": [str(results["task_results"][i]) if results["task_results"][i] else None
|
||||
for i in range(len(parallel_tasks))]
|
||||
},
|
||||
"summary": str(results["task_results"][summary_task.id]) if results["task_results"].get(summary_task.id) else None,
|
||||
"topics": search_topics
|
||||
}
|
||||
|
||||
# 6. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
print("Starting Async AI Agents Examples...")
|
||||
|
||||
try:
|
||||
await run_parallel_tasks()
|
||||
except Exception as e:
|
||||
print(f"Error in main execution: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,248 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
# 1. Define output model for structured results
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
# 2. Define async tool
|
||||
async def async_search_tool(query: str) -> Dict:
|
||||
"""
|
||||
Asynchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
dict: Search results in SearchResult model format
|
||||
"""
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
|
||||
# Format response to match SearchResult model
|
||||
return {
|
||||
"query": query,
|
||||
"results": results,
|
||||
"total_results": len(results)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error during async search: {e}")
|
||||
return {
|
||||
"query": query,
|
||||
"results": [],
|
||||
"total_results": 0
|
||||
}
|
||||
|
||||
# 3. Define async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
print(f"Processed JSON result: {output.json_dict}")
|
||||
elif output.output_format == "Pydantic":
|
||||
print(f"Processed Pydantic result: {output.pydantic}")
|
||||
|
||||
# 4. Create specialized agents
|
||||
async_agent = Agent(
|
||||
name="AsyncSearchAgent",
|
||||
role="Asynchronous Search Specialist",
|
||||
goal="Perform fast and efficient asynchronous searches with structured results",
|
||||
backstory="Expert in parallel search operations and data retrieval",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
summary_agent = Agent(
|
||||
name="SummaryAgent",
|
||||
role="Research Synthesizer",
|
||||
goal="Create comprehensive summaries and identify patterns across multiple search results",
|
||||
backstory="""Expert in analyzing and synthesizing information from multiple sources.
|
||||
Skilled at identifying patterns, trends, and connections between different topics.
|
||||
Specializes in creating clear, structured summaries that highlight key insights.""",
|
||||
self_reflect=True, # Enable self-reflection for better summary quality
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 5. Create async tasks
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="""Search for 'Async programming' and return results in the following JSON format:
|
||||
{
|
||||
"query": "the search query",
|
||||
"results": [
|
||||
{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}
|
||||
],
|
||||
"total_results": number of results
|
||||
}""",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
)
|
||||
|
||||
# 6. Example usage functions
|
||||
async def run_single_task():
|
||||
"""Run single async task"""
|
||||
print("\nRunning Single Async Task...")
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
print(f"Single Task Result: {result}")
|
||||
|
||||
async def run_parallel_tasks():
|
||||
"""Run multiple async tasks in parallel"""
|
||||
print("\nRunning Parallel Async Tasks...")
|
||||
|
||||
# Define different search topics
|
||||
search_topics = [
|
||||
"Latest AI Developments 2024",
|
||||
"Machine Learning Best Practices",
|
||||
"Neural Networks Architecture"
|
||||
]
|
||||
|
||||
# Create tasks for different topics
|
||||
parallel_tasks = [
|
||||
Task(
|
||||
name=f"search_task_{i}",
|
||||
description=f"""Search for '{topic}' and return results in the following JSON format:
|
||||
{{
|
||||
"query": "{topic}",
|
||||
"results": [
|
||||
{{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}}
|
||||
],
|
||||
"total_results": number of results
|
||||
}}""",
|
||||
expected_output="SearchResult model with detailed information",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_json=SearchResult
|
||||
) for i, topic in enumerate(search_topics)
|
||||
]
|
||||
|
||||
# Create summarization task with the specialized summary agent
|
||||
summary_task = Task(
|
||||
name="summary_task",
|
||||
description="""As a Research Synthesizer, analyze the search results and create a comprehensive summary. Your task:
|
||||
|
||||
1. Analyze Results:
|
||||
- Review all search results thoroughly
|
||||
- Extract key findings from each topic
|
||||
- Identify main themes and concepts
|
||||
|
||||
2. Find Connections:
|
||||
- Identify relationships between topics
|
||||
- Spot common patterns or contradictions
|
||||
- Note emerging trends across sources
|
||||
|
||||
3. Create Structured Summary:
|
||||
- Main findings per topic
|
||||
- Cross-cutting themes
|
||||
- Emerging trends
|
||||
- Practical implications
|
||||
- Future directions
|
||||
|
||||
4. Quality Checks:
|
||||
- Ensure all topics are covered
|
||||
- Verify accuracy of connections
|
||||
- Confirm clarity of insights
|
||||
- Validate practical relevance
|
||||
|
||||
Present the summary in a clear, structured format with sections for findings, patterns, trends, and implications.""",
|
||||
expected_output="""A comprehensive research synthesis containing:
|
||||
- Detailed findings from each search topic
|
||||
- Cross-topic patterns and relationships
|
||||
- Emerging trends and their implications
|
||||
- Practical applications and future directions""",
|
||||
agent=summary_agent, # Use the specialized summary agent
|
||||
async_execution=False, # Run synchronously after search tasks
|
||||
callback=async_callback
|
||||
)
|
||||
|
||||
# First run parallel search tasks
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=parallel_tasks, # Only run search tasks first
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
search_results = await agents.astart()
|
||||
print(f"Search Tasks Results: {search_results}")
|
||||
|
||||
# Create task objects with results for context
|
||||
completed_tasks = []
|
||||
for i, topic in enumerate(search_topics):
|
||||
task = Task(
|
||||
name=f"search_task_{i}_result",
|
||||
description=f"Search results for: {topic}",
|
||||
expected_output="Search results from previous task",
|
||||
agent=async_agent,
|
||||
result=search_results["task_results"][i]
|
||||
)
|
||||
completed_tasks.append(task)
|
||||
|
||||
# Update summary task with context from search results
|
||||
summary_task.context = completed_tasks
|
||||
|
||||
# Run summarization task with summary agent
|
||||
summary_agents = PraisonAIAgents(
|
||||
agents=[summary_agent], # Use summary agent for synthesis
|
||||
tasks=[summary_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
summary_result = await summary_agents.astart()
|
||||
print(f"Summary Task Result: {summary_result}")
|
||||
|
||||
# Return results in a serializable format
|
||||
return {
|
||||
"search_results": {
|
||||
"task_status": search_results["task_status"],
|
||||
"task_results": [str(result) if result else None for result in search_results["task_results"]]
|
||||
},
|
||||
"summary": str(summary_result),
|
||||
"topics": search_topics
|
||||
}
|
||||
|
||||
# 7. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
print("Starting Async AI Agents Examples...")
|
||||
|
||||
try:
|
||||
# Run different async patterns
|
||||
await run_single_task()
|
||||
await run_parallel_tasks()
|
||||
except Exception as e:
|
||||
print(f"Error in main execution: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,50 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import json
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
def code_interpreter(code: str):
|
||||
"""
|
||||
A function to demonstrate running Python code dynamically using e2b_code_interpreter.
|
||||
"""
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
|
||||
code_agent = Agent(
|
||||
name="code_agent",
|
||||
llm="gpt-4o-mini",
|
||||
backstory="Expert in writing Python scripts",
|
||||
self_reflect=False
|
||||
)
|
||||
execution_agent = Agent(
|
||||
name="execution_agent",
|
||||
llm="gpt-4o-mini",
|
||||
backstory="Expert in executing Python scripts",
|
||||
self_reflect=False,
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
|
||||
code_agent_task = Task(
|
||||
description="Write a simple Python script to print 'Hello, World!'",
|
||||
expected_output="A Python script that prints 'Hello, World!'",
|
||||
agent=code_agent
|
||||
)
|
||||
execution_agent_task = Task(
|
||||
description="Execute the Python script",
|
||||
expected_output="The output of the Python script",
|
||||
agent=execution_agent
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task])
|
||||
agents.start()
|
||||
@@ -0,0 +1,204 @@
|
||||
from praisonaiagents import (
|
||||
Agent,
|
||||
Task,
|
||||
PraisonAIAgents,
|
||||
error_logs,
|
||||
register_display_callback,
|
||||
sync_display_callbacks,
|
||||
async_display_callbacks
|
||||
)
|
||||
from duckduckgo_search import DDGS
|
||||
from rich.console import Console
|
||||
import json
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Callback functions for different display types
|
||||
def interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
"""Callback for display_interaction"""
|
||||
logging.info(f"""
|
||||
=== INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Markdown: {markdown}
|
||||
""")
|
||||
|
||||
def error_callback(message=None):
|
||||
"""Callback for display_error"""
|
||||
logging.error(f"""
|
||||
=== ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def tool_call_callback(message=None):
|
||||
"""Callback for display_tool_call"""
|
||||
logging.info(f"""
|
||||
=== TOOL CALL ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def instruction_callback(message=None):
|
||||
"""Callback for display_instruction"""
|
||||
logging.info(f"""
|
||||
=== INSTRUCTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def self_reflection_callback(message=None):
|
||||
"""Callback for display_self_reflection"""
|
||||
logging.info(f"""
|
||||
=== SELF REFLECTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def generating_callback(content=None, elapsed_time=None):
|
||||
"""Callback for display_generating"""
|
||||
logging.info(f"""
|
||||
=== GENERATING ===
|
||||
Time: {datetime.now()}
|
||||
Content: {content}
|
||||
Elapsed Time: {elapsed_time}
|
||||
""")
|
||||
|
||||
# Register all callbacks
|
||||
register_display_callback('interaction', interaction_callback)
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
register_display_callback('instruction', instruction_callback)
|
||||
register_display_callback('self_reflection', self_reflection_callback)
|
||||
# register_display_callback('generating', generating_callback)
|
||||
|
||||
def task_callback(output):
|
||||
"""Callback for task completion"""
|
||||
logging.info(f"""
|
||||
=== TASK COMPLETED ===
|
||||
Time: {datetime.now()}
|
||||
Description: {output.description}
|
||||
Agent: {output.agent}
|
||||
Output: {output.raw[:200]}...
|
||||
""")
|
||||
|
||||
def internet_search_tool(query) -> list:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles and URLs.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
def main():
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
tools=[internet_search_tool],
|
||||
llm="gpt-4o",
|
||||
markdown=True,
|
||||
reflect_llm="gpt-4o",
|
||||
min_reflect=2,
|
||||
max_reflect=4
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
verbose=True,
|
||||
allow_delegation=True,
|
||||
llm="gpt-4o",
|
||||
tools=[],
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks with callbacks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher,
|
||||
tools=[internet_search_tool],
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.""",
|
||||
expected_output="A blog post of at least 4 paragraphs",
|
||||
agent=writer,
|
||||
context=[task1],
|
||||
callback=task_callback,
|
||||
tools=[]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="json_task",
|
||||
description="""Create a json object with a title of "My Task" and content of "My content".""",
|
||||
expected_output="""JSON output with title and content""",
|
||||
agent=researcher,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="save_output_task",
|
||||
description="""Save the AI blog post to a file""",
|
||||
expected_output="""File saved successfully""",
|
||||
agent=writer,
|
||||
context=[task2],
|
||||
output_file='test.txt',
|
||||
create_directory=True,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
# Create and run agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=True,
|
||||
process="sequential",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,6 @@
|
||||
from praisonaiagents import Agent, Agents, Tools
|
||||
|
||||
research_agent = Agent(instructions="You are a research agent to search internet about AI 2024", tools=[Tools.internet_search])
|
||||
summarise_agent = Agent(instructions="You are a summarize agent to summarise in points")
|
||||
agents = Agents(agents=[research_agent, summarise_agent])
|
||||
agents.start()
|
||||
@@ -5,6 +5,7 @@ Praison AI Agents - A package for hierarchical AI agent task execution
|
||||
from .agent.agent import Agent
|
||||
from .agents.agents import PraisonAIAgents
|
||||
from .task.task import Task
|
||||
from .tools.tools import Tools
|
||||
from .main import (
|
||||
TaskOutput,
|
||||
ReflectionOutput,
|
||||
@@ -16,11 +17,19 @@ from .main import (
|
||||
display_generating,
|
||||
clean_triple_backticks,
|
||||
error_logs,
|
||||
register_display_callback,
|
||||
sync_display_callbacks,
|
||||
async_display_callbacks,
|
||||
)
|
||||
|
||||
# Add Agents as an alias for PraisonAIAgents
|
||||
Agents = PraisonAIAgents
|
||||
|
||||
__all__ = [
|
||||
'Agent',
|
||||
'PraisonAIAgents',
|
||||
'Agents',
|
||||
'Tools',
|
||||
'Task',
|
||||
'TaskOutput',
|
||||
'ReflectionOutput',
|
||||
@@ -32,4 +41,7 @@ __all__ = [
|
||||
'display_generating',
|
||||
'clean_triple_backticks',
|
||||
'error_logs',
|
||||
'register_display_callback',
|
||||
'sync_display_callbacks',
|
||||
'async_display_callbacks',
|
||||
]
|
||||
@@ -1,9 +1,12 @@
|
||||
import logging
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from typing import List, Optional, Any, Dict, Union, Literal
|
||||
import json
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import List, Optional, Any, Dict, Union, Literal, TYPE_CHECKING
|
||||
from rich.console import Console
|
||||
from rich.live import Live
|
||||
from openai import AsyncOpenAI
|
||||
from ..main import (
|
||||
display_error,
|
||||
display_tool_call,
|
||||
@@ -16,6 +19,9 @@ from ..main import (
|
||||
error_logs
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..task.task import Task
|
||||
|
||||
class Agent:
|
||||
def _generate_tool_definition(self, function_name):
|
||||
"""
|
||||
@@ -129,11 +135,12 @@ class Agent:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
role: str,
|
||||
goal: str,
|
||||
backstory: str,
|
||||
llm: Optional[Union[str, Any]] = "gpt-4o",
|
||||
name: Optional[str] = None,
|
||||
role: Optional[str] = None,
|
||||
goal: Optional[str] = None,
|
||||
backstory: Optional[str] = None,
|
||||
instructions: Optional[str] = None,
|
||||
llm: Optional[Union[str, Any]] = None,
|
||||
tools: Optional[List[Any]] = None,
|
||||
function_calling_llm: Optional[Any] = None,
|
||||
max_iter: int = 20,
|
||||
@@ -155,16 +162,35 @@ class Agent:
|
||||
knowledge_sources: Optional[List[Any]] = None,
|
||||
use_system_prompt: Optional[bool] = True,
|
||||
markdown: bool = True,
|
||||
self_reflect: bool = True,
|
||||
self_reflect: Optional[bool] = None,
|
||||
max_reflect: int = 3,
|
||||
min_reflect: int = 1,
|
||||
reflect_llm: Optional[str] = None
|
||||
):
|
||||
self.name = name
|
||||
self.role = role
|
||||
self.goal = goal
|
||||
self.backstory = backstory
|
||||
self.llm = llm
|
||||
# Handle backward compatibility for required fields
|
||||
if all(x is None for x in [name, role, goal, backstory, instructions]):
|
||||
raise ValueError("At least one of name, role, goal, backstory, or instructions must be provided")
|
||||
|
||||
# If instructions are provided, use them to set role, goal, and backstory
|
||||
if instructions:
|
||||
self.name = name or "Agent"
|
||||
self.role = role or "Assistant"
|
||||
self.goal = goal or instructions
|
||||
self.backstory = backstory or instructions
|
||||
# Set self_reflect to False by default for instruction-based agents
|
||||
self.self_reflect = False if self_reflect is None else self_reflect
|
||||
else:
|
||||
# Use provided values or defaults
|
||||
self.name = name or "Agent"
|
||||
self.role = role or "Assistant"
|
||||
self.goal = goal or "Help the user with their tasks"
|
||||
self.backstory = backstory or "I am an AI assistant"
|
||||
# Default to True for traditional agents if not specified
|
||||
self.self_reflect = True if self_reflect is None else self_reflect
|
||||
|
||||
self.instructions = instructions
|
||||
# Check for model name in environment variable if not provided
|
||||
self.llm = llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
|
||||
self.tools = tools if tools else [] # Store original tools
|
||||
self.function_calling_llm = function_calling_llm
|
||||
self.max_iter = max_iter
|
||||
@@ -187,11 +213,32 @@ class Agent:
|
||||
self.use_system_prompt = use_system_prompt
|
||||
self.chat_history = []
|
||||
self.markdown = markdown
|
||||
self.self_reflect = self_reflect
|
||||
self.max_reflect = max_reflect
|
||||
self.min_reflect = min_reflect
|
||||
self.reflect_llm = reflect_llm
|
||||
# Use the same model selection logic for reflect_llm
|
||||
self.reflect_llm = reflect_llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
|
||||
self.console = Console() # Create a single console instance for the agent
|
||||
|
||||
# Initialize system prompt
|
||||
self.system_prompt = f"""{self.backstory}\n
|
||||
Your Role: {self.role}\n
|
||||
Your Goal: {self.goal}
|
||||
"""
|
||||
|
||||
def generate_task(self) -> 'Task':
|
||||
"""Generate a Task object from the agent's instructions"""
|
||||
from ..task.task import Task
|
||||
|
||||
description = self.instructions if self.instructions else f"Execute task as {self.role} with goal: {self.goal}"
|
||||
expected_output = "Complete the assigned task successfully"
|
||||
|
||||
return Task(
|
||||
name=self.name,
|
||||
description=description,
|
||||
expected_output=expected_output,
|
||||
agent=self,
|
||||
tools=self.tools
|
||||
)
|
||||
|
||||
def execute_tool(self, function_name, arguments):
|
||||
"""
|
||||
@@ -347,7 +394,7 @@ class Agent:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
return None
|
||||
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None):
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
|
||||
if self.use_system_prompt:
|
||||
system_prompt = f"""{self.backstory}\n
|
||||
Your Role: {self.role}\n
|
||||
@@ -355,6 +402,8 @@ Your Goal: {self.goal}
|
||||
"""
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
|
||||
elif output_pydantic:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_pydantic.schema_json()}"
|
||||
else:
|
||||
system_prompt = None
|
||||
|
||||
@@ -363,9 +412,9 @@ Your Goal: {self.goal}
|
||||
messages.append({"role": "system", "content": system_prompt})
|
||||
messages.extend(self.chat_history)
|
||||
|
||||
# Modify prompt if output_json is specified
|
||||
# Modify prompt if output_json or output_pydantic is specified
|
||||
original_prompt = prompt
|
||||
if output_json:
|
||||
if output_json or output_pydantic:
|
||||
if isinstance(prompt, str):
|
||||
prompt += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
elif isinstance(prompt, list):
|
||||
@@ -440,23 +489,15 @@ Your Goal: {self.goal}
|
||||
return None
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
# Handle output_json if specified
|
||||
if output_json:
|
||||
try:
|
||||
# Clean the response text to get only JSON
|
||||
cleaned_json = self.clean_json_output(response_text)
|
||||
# Parse into Pydantic model
|
||||
parsed_model = output_json.model_validate_json(cleaned_json)
|
||||
# Add to chat history and return
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown,
|
||||
generation_time=time.time() - start_time, console=self.console)
|
||||
return parsed_model
|
||||
except Exception as e:
|
||||
display_error(f"Failed to parse response as {output_json.__name__}: {e}")
|
||||
return None
|
||||
# Handle output_json or output_pydantic if specified
|
||||
if output_json or output_pydantic:
|
||||
# Add to chat history and return raw response
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown,
|
||||
generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
if not self.self_reflect:
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
@@ -536,4 +577,138 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
cleaned = cleaned[len("```"):].strip()
|
||||
if cleaned.endswith("```"):
|
||||
cleaned = cleaned[:-3].strip()
|
||||
return cleaned
|
||||
return cleaned
|
||||
|
||||
async def achat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
|
||||
"""Async version of chat method"""
|
||||
try:
|
||||
# Build system prompt
|
||||
system_prompt = self.system_prompt
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
|
||||
elif output_pydantic:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_pydantic.schema_json()}"
|
||||
|
||||
# Build messages
|
||||
if isinstance(prompt, str):
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt + ("\nReturn ONLY a valid JSON object. No other text or explanation." if (output_json or output_pydantic) else "")}
|
||||
]
|
||||
else:
|
||||
# For multimodal prompts
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
if output_json or output_pydantic:
|
||||
# Add JSON instruction to text content
|
||||
for item in messages[-1]["content"]:
|
||||
if item["type"] == "text":
|
||||
item["text"] += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
break
|
||||
|
||||
# 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__))
|
||||
|
||||
# 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
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
return None
|
||||
|
||||
async def _achat_completion(self, response, tools):
|
||||
"""Async version of _chat_completion method"""
|
||||
try:
|
||||
message = response.choices[0].message
|
||||
if not hasattr(message, 'tool_calls') or not message.tool_calls:
|
||||
return message.content
|
||||
|
||||
results = []
|
||||
for tool_call in message.tool_calls:
|
||||
try:
|
||||
function_name = tool_call.function.name
|
||||
arguments = json.loads(tool_call.function.arguments)
|
||||
|
||||
# Find the matching tool
|
||||
tool = next((t for t in tools if t.__name__ == function_name), None)
|
||||
if not tool:
|
||||
display_error(f"Tool {function_name} not found")
|
||||
continue
|
||||
|
||||
# Check if the tool is async
|
||||
if asyncio.iscoroutinefunction(tool):
|
||||
result = await tool(**arguments)
|
||||
else:
|
||||
# Run sync function in executor to avoid blocking
|
||||
loop = asyncio.get_event_loop()
|
||||
result = await loop.run_in_executor(None, lambda: tool(**arguments))
|
||||
|
||||
results.append(result)
|
||||
except Exception as e:
|
||||
display_error(f"Error executing tool {function_name}: {e}")
|
||||
results.append(None)
|
||||
|
||||
# If we have results, format them into a response
|
||||
if results:
|
||||
formatted_results = "\n".join([str(r) for r in results if r is not None])
|
||||
if formatted_results:
|
||||
messages = [
|
||||
{"role": "system", "content": self.system_prompt},
|
||||
{"role": "assistant", "content": "Here are the tool results:"},
|
||||
{"role": "user", "content": formatted_results + "\nPlease process these results and provide a final response."}
|
||||
]
|
||||
try:
|
||||
async_client = AsyncOpenAI()
|
||||
final_response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=0.2
|
||||
)
|
||||
return final_response.choices[0].message.content
|
||||
except Exception as e:
|
||||
display_error(f"Error in final chat completion: {e}")
|
||||
return formatted_results
|
||||
return formatted_results
|
||||
return None
|
||||
except Exception as e:
|
||||
display_error(f"Error in _achat_completion: {e}")
|
||||
return None
|
||||
@@ -11,6 +11,7 @@ from ..main import display_error, TaskOutput, error_logs, client
|
||||
from ..agent.agent import Agent
|
||||
from ..task.task import Task
|
||||
from ..process.process import Process, LoopItems
|
||||
import asyncio
|
||||
|
||||
def encode_file_to_base64(file_path: str) -> str:
|
||||
"""Base64-encode a file."""
|
||||
@@ -40,7 +41,10 @@ def process_video(video_path: str, seconds_per_frame=2):
|
||||
return base64_frames
|
||||
|
||||
class PraisonAIAgents:
|
||||
def __init__(self, agents, tasks, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None):
|
||||
def __init__(self, agents, tasks=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None):
|
||||
if not agents:
|
||||
raise ValueError("At least one agent must be provided")
|
||||
|
||||
self.agents = agents
|
||||
self.tasks = {}
|
||||
if max_retries < 3:
|
||||
@@ -50,12 +54,41 @@ class PraisonAIAgents:
|
||||
self.verbose = verbose
|
||||
self.max_retries = max_retries
|
||||
self.process = process
|
||||
if not manager_llm:
|
||||
logging.debug("No manager_llm provided. Using OPENAI_MODEL_NAME environment variable or defaulting to 'gpt-4o'")
|
||||
self.manager_llm = manager_llm if manager_llm else os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
|
||||
|
||||
# Check for manager_llm in environment variable if not provided
|
||||
self.manager_llm = manager_llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
|
||||
if self.verbose:
|
||||
logging.info(f"Using model {self.manager_llm} for manager")
|
||||
|
||||
# If no tasks provided, generate them from agents
|
||||
if tasks is None:
|
||||
tasks = []
|
||||
for agent in self.agents:
|
||||
task = agent.generate_task()
|
||||
tasks.append(task)
|
||||
logging.info(f"Auto-generated {len(tasks)} tasks from agents")
|
||||
else:
|
||||
# Validate tasks for backward compatibility
|
||||
if not tasks:
|
||||
raise ValueError("If tasks are provided, at least one task must be present")
|
||||
logging.info(f"Using {len(tasks)} provided tasks")
|
||||
|
||||
# Add tasks and set their status
|
||||
for task in tasks:
|
||||
self.add_task(task)
|
||||
task.status = "not started"
|
||||
|
||||
# If tasks were auto-generated from agents or process is sequential, set up sequential flow
|
||||
if len(tasks) > 1 and (process == "sequential" or all(task.next_tasks == [] for task in tasks)):
|
||||
for i in range(len(tasks) - 1):
|
||||
# Set up next task relationship
|
||||
tasks[i].next_tasks = [tasks[i + 1].name]
|
||||
# Set up context for the next task to include the current task
|
||||
if tasks[i + 1].context is None:
|
||||
tasks[i + 1].context = []
|
||||
tasks[i + 1].context.append(tasks[i])
|
||||
logging.info("Set up sequential flow with automatic context passing")
|
||||
|
||||
self._state = {} # Add state storage at PraisonAIAgents level
|
||||
|
||||
def add_task(self, task):
|
||||
@@ -82,7 +115,8 @@ class PraisonAIAgents:
|
||||
return True
|
||||
return len(agent_output.strip()) > 0
|
||||
|
||||
def execute_task(self, task_id):
|
||||
async def aexecute_task(self, task_id):
|
||||
"""Async version of execute_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
@@ -117,9 +151,226 @@ Expected Output: {task.expected_output}.
|
||||
else:
|
||||
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
|
||||
task_prompt += f"""
|
||||
Here are the results of previous tasks that might be useful:\n
|
||||
{context_results}
|
||||
"""
|
||||
Here are the results of previous tasks that might be useful:\n
|
||||
{context_results}
|
||||
"""
|
||||
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
|
||||
|
||||
if self.verbose >= 2:
|
||||
logging.info(f"Executing task {task_id}: {task.description} using {executor_agent.name}")
|
||||
logging.debug(f"Starting execution of task {task_id} with prompt:\n{task_prompt}")
|
||||
|
||||
if task.images:
|
||||
def _get_multimodal_message(text_prompt, images):
|
||||
content = [{"type": "text", "text": text_prompt}]
|
||||
|
||||
for img in images:
|
||||
# If local file path for a valid image
|
||||
if os.path.exists(img):
|
||||
ext = os.path.splitext(img)[1].lower()
|
||||
# If it's a .mp4, convert to frames
|
||||
if ext == ".mp4":
|
||||
frames = process_video(img, seconds_per_frame=1)
|
||||
content.append({"type": "text", "text": "These are frames from the video."})
|
||||
for f in frames:
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {"url": f"data:image/jpg;base64,{f}"}
|
||||
})
|
||||
else:
|
||||
encoded = encode_file_to_base64(img)
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": f"data:image/{ext.lstrip('.')};base64,{encoded}"
|
||||
}
|
||||
})
|
||||
else:
|
||||
# Treat as a remote URL
|
||||
content.append({
|
||||
"type": "image_url",
|
||||
"image_url": {"url": img}
|
||||
})
|
||||
return content
|
||||
|
||||
agent_output = await executor_agent.achat(
|
||||
_get_multimodal_message(task_prompt, task.images),
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
else:
|
||||
agent_output = await executor_agent.achat(
|
||||
task_prompt,
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
|
||||
if agent_output:
|
||||
task_output = TaskOutput(
|
||||
description=task.description,
|
||||
summary=task.description[:10],
|
||||
raw=agent_output,
|
||||
agent=executor_agent.name,
|
||||
output_format="RAW"
|
||||
)
|
||||
|
||||
if task.output_json:
|
||||
cleaned = self.clean_json_output(agent_output)
|
||||
try:
|
||||
parsed = json.loads(cleaned)
|
||||
task_output.json_dict = parsed
|
||||
task_output.output_format = "JSON"
|
||||
except:
|
||||
logging.warning(f"Warning: Could not parse output of task {task_id} as JSON")
|
||||
logging.debug(f"Output that failed JSON parsing: {agent_output}")
|
||||
|
||||
if task.output_pydantic:
|
||||
cleaned = self.clean_json_output(agent_output)
|
||||
try:
|
||||
parsed = json.loads(cleaned)
|
||||
pyd_obj = task.output_pydantic(**parsed)
|
||||
task_output.pydantic = pyd_obj
|
||||
task_output.output_format = "Pydantic"
|
||||
except:
|
||||
logging.warning(f"Warning: Could not parse output of task {task_id} as Pydantic Model")
|
||||
logging.debug(f"Output that failed Pydantic parsing: {agent_output}")
|
||||
|
||||
task.result = task_output
|
||||
return task_output
|
||||
else:
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
async def arun_task(self, task_id):
|
||||
"""Async version of run_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
task = self.tasks[task_id]
|
||||
if task.status == "completed":
|
||||
logging.info(f"Task with ID {task_id} is already completed")
|
||||
return
|
||||
|
||||
retries = 0
|
||||
while task.status != "completed" and retries < self.max_retries:
|
||||
logging.debug(f"Attempt {retries+1} for task {task_id}")
|
||||
if task.status in ["not started", "in progress"]:
|
||||
task_output = await self.aexecute_task(task_id)
|
||||
if task_output and self.completion_checker(task, task_output.raw):
|
||||
task.status = "completed"
|
||||
if task.callback:
|
||||
await task.execute_callback(task_output)
|
||||
self.save_output_to_file(task, task_output)
|
||||
if self.verbose >= 1:
|
||||
logging.info(f"Task {task_id} completed successfully.")
|
||||
else:
|
||||
task.status = "in progress"
|
||||
if self.verbose >= 1:
|
||||
logging.info(f"Task {task_id} not completed, retrying")
|
||||
await asyncio.sleep(1)
|
||||
retries += 1
|
||||
else:
|
||||
if task.status == "failed":
|
||||
logging.info("Task is failed, resetting to in-progress for another try...")
|
||||
task.status = "in progress"
|
||||
else:
|
||||
logging.info("Invalid Task status")
|
||||
break
|
||||
|
||||
if retries == self.max_retries and task.status != "completed":
|
||||
logging.info(f"Task {task_id} failed after {self.max_retries} retries.")
|
||||
|
||||
async def arun_all_tasks(self):
|
||||
"""Async version of run_all_tasks method"""
|
||||
process = Process(
|
||||
tasks=self.tasks,
|
||||
agents=self.agents,
|
||||
manager_llm=self.manager_llm,
|
||||
verbose=self.verbose
|
||||
)
|
||||
|
||||
if self.process == "workflow":
|
||||
async for task_id in process.aworkflow():
|
||||
if self.tasks[task_id].async_execution:
|
||||
await self.arun_task(task_id)
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
elif self.process == "sequential":
|
||||
async for task_id in process.asequential():
|
||||
if self.tasks[task_id].async_execution:
|
||||
await self.arun_task(task_id)
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
elif self.process == "hierarchical":
|
||||
async for task_id in process.ahierarchical():
|
||||
if isinstance(task_id, Task):
|
||||
task_id = self.add_task(task_id)
|
||||
if self.tasks[task_id].async_execution:
|
||||
await self.arun_task(task_id)
|
||||
else:
|
||||
self.run_task(task_id)
|
||||
|
||||
async def astart(self):
|
||||
"""Async version of start method"""
|
||||
await self.arun_all_tasks()
|
||||
return {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
|
||||
}
|
||||
|
||||
def save_output_to_file(self, task, task_output):
|
||||
if task.output_file:
|
||||
try:
|
||||
if task.create_directory:
|
||||
os.makedirs(os.path.dirname(task.output_file), exist_ok=True)
|
||||
with open(task.output_file, "w") as f:
|
||||
f.write(str(task_output))
|
||||
if self.verbose >= 1:
|
||||
logging.info(f"Task output saved to {task.output_file}")
|
||||
except Exception as e:
|
||||
display_error(f"Error saving task output to file: {e}")
|
||||
|
||||
def execute_task(self, task_id):
|
||||
"""Synchronous version of execute_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
task = self.tasks[task_id]
|
||||
|
||||
# Only import multimodal dependencies if task has images
|
||||
if task.images and task.status == "not started":
|
||||
try:
|
||||
import cv2
|
||||
import base64
|
||||
from moviepy import VideoFileClip
|
||||
except ImportError as e:
|
||||
display_error(f"Error: Missing required dependencies for image/video processing: {e}")
|
||||
display_error("Please install with: pip install opencv-python moviepy")
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
if task.status == "not started":
|
||||
task.status = "in progress"
|
||||
|
||||
executor_agent = task.agent
|
||||
|
||||
task_prompt = f"""
|
||||
You need to do the following task: {task.description}.
|
||||
Expected Output: {task.expected_output}.
|
||||
"""
|
||||
if task.context:
|
||||
context_results = ""
|
||||
for context_task in task.context:
|
||||
if context_task.result:
|
||||
context_results += f"Result of previous task {context_task.name if context_task.name else context_task.description}: {context_task.result.raw}\n"
|
||||
else:
|
||||
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
|
||||
task_prompt += f"""
|
||||
Here are the results of previous tasks that might be useful:\n
|
||||
{context_results}
|
||||
"""
|
||||
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
|
||||
|
||||
if self.verbose >= 2:
|
||||
@@ -161,10 +412,17 @@ Expected Output: {task.expected_output}.
|
||||
|
||||
agent_output = executor_agent.chat(
|
||||
_get_multimodal_message(task_prompt, task.images),
|
||||
tools=task.tools
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
else:
|
||||
agent_output = executor_agent.chat(task_prompt, tools=task.tools)
|
||||
agent_output = executor_agent.chat(
|
||||
task_prompt,
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
|
||||
if agent_output:
|
||||
task_output = TaskOutput(
|
||||
@@ -202,19 +460,8 @@ Expected Output: {task.expected_output}.
|
||||
task.status = "failed"
|
||||
return None
|
||||
|
||||
def save_output_to_file(self, task, task_output):
|
||||
if task.output_file:
|
||||
try:
|
||||
if task.create_directory:
|
||||
os.makedirs(os.path.dirname(task.output_file), exist_ok=True)
|
||||
with open(task.output_file, "w") as f:
|
||||
f.write(str(task_output))
|
||||
if self.verbose >= 1:
|
||||
logging.info(f"Task output saved to {task.output_file}")
|
||||
except Exception as e:
|
||||
display_error(f"Error saving task output to file: {e}")
|
||||
|
||||
def run_task(self, task_id):
|
||||
"""Synchronous version of run_task method"""
|
||||
if task_id not in self.tasks:
|
||||
display_error(f"Error: Task with ID {task_id} does not exist")
|
||||
return
|
||||
@@ -253,7 +500,7 @@ Expected Output: {task.expected_output}.
|
||||
logging.info(f"Task {task_id} failed after {self.max_retries} retries.")
|
||||
|
||||
def run_all_tasks(self):
|
||||
"""Execute tasks based on execution mode"""
|
||||
"""Synchronous version of run_all_tasks method"""
|
||||
process = Process(
|
||||
tasks=self.tasks,
|
||||
agents=self.agents,
|
||||
|
||||
@@ -12,6 +12,7 @@ from rich.text import Text
|
||||
from rich.markdown import Markdown
|
||||
from rich.logging import RichHandler
|
||||
from rich.live import Live
|
||||
import asyncio
|
||||
|
||||
LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
|
||||
|
||||
@@ -25,6 +26,50 @@ logging.basicConfig(
|
||||
# Global list to store error logs
|
||||
error_logs = []
|
||||
|
||||
# Separate registries for sync and async callbacks
|
||||
sync_display_callbacks = {}
|
||||
async_display_callbacks = {}
|
||||
|
||||
# At the top of the file, add display_callbacks to __all__
|
||||
__all__ = [
|
||||
'error_logs',
|
||||
'register_display_callback',
|
||||
'sync_display_callbacks',
|
||||
'async_display_callbacks',
|
||||
# ... other exports
|
||||
]
|
||||
|
||||
def register_display_callback(display_type: str, callback_fn, is_async: bool = False):
|
||||
"""Register a synchronous or asynchronous callback function for a specific display type.
|
||||
|
||||
Args:
|
||||
display_type (str): Type of display event ('interaction', 'self_reflection', etc.)
|
||||
callback_fn: The callback function to register
|
||||
is_async (bool): Whether the callback is asynchronous
|
||||
"""
|
||||
if is_async:
|
||||
async_display_callbacks[display_type] = callback_fn
|
||||
else:
|
||||
sync_display_callbacks[display_type] = callback_fn
|
||||
|
||||
async def execute_callback(display_type: str, **kwargs):
|
||||
"""Execute both sync and async callbacks for a given display type.
|
||||
|
||||
Args:
|
||||
display_type (str): Type of display event
|
||||
**kwargs: Arguments to pass to the callback functions
|
||||
"""
|
||||
# Execute synchronous callback if registered
|
||||
if display_type in sync_display_callbacks:
|
||||
callback = sync_display_callbacks[display_type]
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, lambda: callback(**kwargs))
|
||||
|
||||
# Execute asynchronous callback if registered
|
||||
if display_type in async_display_callbacks:
|
||||
callback = async_display_callbacks[display_type]
|
||||
await callback(**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():
|
||||
@@ -46,21 +91,30 @@ def _clean_display_content(content: str, max_length: int = 20000) -> str:
|
||||
return content.strip()
|
||||
|
||||
def display_interaction(message, response, markdown=True, generation_time=None, console=None):
|
||||
"""Display the interaction between user and assistant."""
|
||||
"""Synchronous version of display_interaction."""
|
||||
if console is None:
|
||||
console = Console()
|
||||
if generation_time:
|
||||
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
|
||||
|
||||
# Handle multimodal content (list)
|
||||
|
||||
if isinstance(message, list):
|
||||
# Extract just the text content from the multimodal message
|
||||
text_content = next((item["text"] for item in message if item["type"] == "text"), "")
|
||||
message = text_content
|
||||
|
||||
message = _clean_display_content(str(message))
|
||||
response = _clean_display_content(str(response))
|
||||
|
||||
# Execute synchronous callback if registered
|
||||
if 'interaction' in sync_display_callbacks:
|
||||
sync_display_callbacks['interaction'](
|
||||
message=message,
|
||||
response=response,
|
||||
markdown=markdown,
|
||||
generation_time=generation_time
|
||||
)
|
||||
|
||||
# Rest of the display logic...
|
||||
if generation_time:
|
||||
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
|
||||
|
||||
if markdown:
|
||||
console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
|
||||
@@ -74,6 +128,11 @@ def display_self_reflection(message: str, console=None):
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'self_reflection' in sync_display_callbacks:
|
||||
sync_display_callbacks['self_reflection'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
|
||||
|
||||
def display_instruction(message: str, console=None):
|
||||
@@ -82,6 +141,11 @@ def display_instruction(message: str, console=None):
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'instruction' in sync_display_callbacks:
|
||||
sync_display_callbacks['instruction'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
|
||||
|
||||
def display_tool_call(message: str, console=None):
|
||||
@@ -90,6 +154,11 @@ def display_tool_call(message: str, console=None):
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'tool_call' in sync_display_callbacks:
|
||||
sync_display_callbacks['tool_call'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
|
||||
|
||||
def display_error(message: str, console=None):
|
||||
@@ -98,19 +167,138 @@ def display_error(message: str, console=None):
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'error' in sync_display_callbacks:
|
||||
sync_display_callbacks['error'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
|
||||
# Store errors
|
||||
error_logs.append(message)
|
||||
|
||||
def display_generating(content: str = "", start_time: Optional[float] = None):
|
||||
if not content or not str(content).strip():
|
||||
return Panel("", title="", border_style="green") # Return empty panel when no content
|
||||
return Panel("", title="", border_style="green")
|
||||
|
||||
elapsed_str = ""
|
||||
if start_time is not None:
|
||||
elapsed = time.time() - start_time
|
||||
elapsed_str = f" {elapsed:.1f}s"
|
||||
|
||||
content = _clean_display_content(str(content))
|
||||
|
||||
# Execute callback if registered
|
||||
if 'generating' in sync_display_callbacks:
|
||||
sync_display_callbacks['generating'](
|
||||
content=content,
|
||||
elapsed_time=elapsed_str.strip() if elapsed_str else None
|
||||
)
|
||||
|
||||
return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
|
||||
|
||||
# Async versions with 'a' prefix
|
||||
async def adisplay_interaction(message, response, markdown=True, generation_time=None, console=None):
|
||||
"""Async version of display_interaction."""
|
||||
if console is None:
|
||||
console = Console()
|
||||
|
||||
if isinstance(message, list):
|
||||
text_content = next((item["text"] for item in message if item["type"] == "text"), "")
|
||||
message = text_content
|
||||
|
||||
message = _clean_display_content(str(message))
|
||||
response = _clean_display_content(str(response))
|
||||
|
||||
# Execute callbacks
|
||||
await execute_callback(
|
||||
'interaction',
|
||||
message=message,
|
||||
response=response,
|
||||
markdown=markdown,
|
||||
generation_time=generation_time
|
||||
)
|
||||
|
||||
# Rest of the display logic...
|
||||
if generation_time:
|
||||
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
|
||||
|
||||
if markdown:
|
||||
console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
|
||||
else:
|
||||
console.print(Panel.fit(Text(message, style="bold green"), title="Message", border_style="cyan"))
|
||||
console.print(Panel.fit(Text(response, style="bold blue"), title="Response", border_style="cyan"))
|
||||
|
||||
async def adisplay_self_reflection(message: str, console=None):
|
||||
"""Async version of display_self_reflection."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'self_reflection' in async_display_callbacks:
|
||||
await async_display_callbacks['self_reflection'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
|
||||
|
||||
async def adisplay_instruction(message: str, console=None):
|
||||
"""Async version of display_instruction."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'instruction' in async_display_callbacks:
|
||||
await async_display_callbacks['instruction'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
|
||||
|
||||
async def adisplay_tool_call(message: str, console=None):
|
||||
"""Async version of display_tool_call."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'tool_call' in async_display_callbacks:
|
||||
await async_display_callbacks['tool_call'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
|
||||
|
||||
async def adisplay_error(message: str, console=None):
|
||||
"""Async version of display_error."""
|
||||
if not message or not message.strip():
|
||||
return
|
||||
if console is None:
|
||||
console = Console()
|
||||
message = _clean_display_content(str(message))
|
||||
|
||||
if 'error' in async_display_callbacks:
|
||||
await async_display_callbacks['error'](message=message)
|
||||
|
||||
console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
|
||||
error_logs.append(message)
|
||||
|
||||
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")
|
||||
|
||||
elapsed_str = ""
|
||||
if start_time is not None:
|
||||
elapsed = time.time() - start_time
|
||||
elapsed_str = f" {elapsed:.1f}s"
|
||||
|
||||
content = _clean_display_content(str(content))
|
||||
|
||||
if 'generating' in async_display_callbacks:
|
||||
await async_display_callbacks['generating'](
|
||||
content=content,
|
||||
elapsed_time=elapsed_str.strip() if elapsed_str else None
|
||||
)
|
||||
|
||||
return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
|
||||
|
||||
def clean_triple_backticks(text: str) -> str:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import logging
|
||||
from typing import Dict, Optional, List, Any
|
||||
import asyncio
|
||||
from typing import Dict, Optional, List, Any, AsyncGenerator
|
||||
from pydantic import BaseModel
|
||||
from ..agent.agent import Agent
|
||||
from ..task.task import Task
|
||||
@@ -15,7 +16,275 @@ class Process:
|
||||
self.manager_llm = manager_llm
|
||||
self.verbose = verbose
|
||||
|
||||
async def aworkflow(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of workflow method"""
|
||||
# Build workflow relationships first
|
||||
for task in self.tasks.values():
|
||||
if task.next_tasks:
|
||||
for next_task_name in task.next_tasks:
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
if next_task:
|
||||
next_task.previous_tasks.append(task.name)
|
||||
|
||||
# Find start task
|
||||
start_task = None
|
||||
for task_id, task in self.tasks.items():
|
||||
if task.is_start:
|
||||
start_task = task
|
||||
break
|
||||
|
||||
if not start_task:
|
||||
start_task = list(self.tasks.values())[0]
|
||||
logging.info("No start task marked, using first task")
|
||||
|
||||
current_task = start_task
|
||||
visited_tasks = set()
|
||||
loop_data = {} # Store loop-specific data
|
||||
|
||||
while current_task and current_task.id not in visited_tasks:
|
||||
task_id = current_task.id
|
||||
logging.info(f"Executing workflow task: {current_task.name if current_task.name else task_id}")
|
||||
|
||||
# Add context from previous tasks to description
|
||||
if current_task.previous_tasks or current_task.context:
|
||||
context = "\nInput data from previous tasks:"
|
||||
|
||||
# Add data from previous tasks in workflow
|
||||
for prev_name in current_task.previous_tasks:
|
||||
prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
|
||||
if prev_task and prev_task.result:
|
||||
# Handle loop data
|
||||
if current_task.task_type == "loop":
|
||||
# create a loop manager Agent
|
||||
loop_manager = Agent(
|
||||
name="Loop Manager",
|
||||
role="Loop data processor",
|
||||
goal="Process loop data and convert it to list format",
|
||||
backstory="Expert at handling loop data and converting it to proper format",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# get the loop data convert it to list using calling Agent class chat
|
||||
loop_prompt = f"""
|
||||
Process this data into a list format:
|
||||
{prev_task.result.raw}
|
||||
|
||||
Return a JSON object with an 'items' array containing the items to process.
|
||||
"""
|
||||
if current_task.async_execution:
|
||||
loop_data_str = await loop_manager.achat(
|
||||
prompt=loop_prompt,
|
||||
output_json=LoopItems
|
||||
)
|
||||
else:
|
||||
loop_data_str = loop_manager.chat(
|
||||
prompt=loop_prompt,
|
||||
output_json=LoopItems
|
||||
)
|
||||
|
||||
try:
|
||||
# The response will already be parsed into LoopItems model
|
||||
loop_data[f"loop_{current_task.name}"] = {
|
||||
"items": loop_data_str.items,
|
||||
"index": 0,
|
||||
"remaining": len(loop_data_str.items)
|
||||
}
|
||||
context += f"\nCurrent loop item: {loop_data_str.items[0]}"
|
||||
except Exception as e:
|
||||
display_error(f"Failed to process loop data: {e}")
|
||||
context += f"\n{prev_name}: {prev_task.result.raw}"
|
||||
else:
|
||||
context += f"\n{prev_name}: {prev_task.result.raw}"
|
||||
|
||||
# Add data from context tasks
|
||||
if current_task.context:
|
||||
for ctx_task in current_task.context:
|
||||
if ctx_task.result and ctx_task.name != current_task.name:
|
||||
context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
|
||||
|
||||
# Update task description with context
|
||||
current_task.description = current_task.description + context
|
||||
|
||||
# Execute task using existing run_task method
|
||||
yield task_id
|
||||
visited_tasks.add(task_id)
|
||||
|
||||
# Handle loop progression
|
||||
if current_task.task_type == "loop":
|
||||
loop_key = f"loop_{current_task.name}"
|
||||
if loop_key in loop_data:
|
||||
loop_info = loop_data[loop_key]
|
||||
loop_info["index"] += 1
|
||||
has_more = loop_info["remaining"] > 0
|
||||
|
||||
# Update result to trigger correct condition
|
||||
if current_task.result:
|
||||
result = current_task.result.raw
|
||||
if has_more:
|
||||
result += "\nmore"
|
||||
else:
|
||||
result += "\ndone"
|
||||
current_task.result.raw = result
|
||||
|
||||
# Determine next task based on result
|
||||
next_task = None
|
||||
if current_task.result:
|
||||
if current_task.task_type in ["decision", "loop"]:
|
||||
result = current_task.result.raw.lower()
|
||||
# Check conditions
|
||||
for condition, tasks in current_task.condition.items():
|
||||
if condition.lower() in result and tasks:
|
||||
next_task_name = tasks[0]
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
# For loops, allow revisiting the same task
|
||||
if next_task and next_task.id == current_task.id:
|
||||
visited_tasks.discard(current_task.id)
|
||||
break
|
||||
|
||||
if not next_task and current_task.next_tasks:
|
||||
next_task_name = current_task.next_tasks[0]
|
||||
next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
|
||||
|
||||
current_task = next_task
|
||||
if not current_task:
|
||||
logging.info("Workflow execution completed")
|
||||
break
|
||||
|
||||
async def asequential(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of sequential method"""
|
||||
for task_id in self.tasks:
|
||||
if self.tasks[task_id].status != "completed":
|
||||
yield task_id
|
||||
|
||||
async def ahierarchical(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of hierarchical method"""
|
||||
logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
|
||||
manager_agent = Agent(
|
||||
name="Manager",
|
||||
role="Project manager",
|
||||
goal="Manage the entire flow of tasks and delegate them to the right agent",
|
||||
backstory="Expert project manager to coordinate tasks among agents",
|
||||
llm=self.manager_llm,
|
||||
verbose=self.verbose,
|
||||
markdown=True,
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
class ManagerInstructions(BaseModel):
|
||||
task_id: int
|
||||
agent_name: str
|
||||
action: str
|
||||
|
||||
manager_task = Task(
|
||||
name="manager_task",
|
||||
description="Decide the order of tasks and which agent executes them",
|
||||
expected_output="All tasks completed successfully",
|
||||
agent=manager_agent
|
||||
)
|
||||
manager_task_id = yield manager_task
|
||||
logging.info(f"Created manager task with ID {manager_task_id}")
|
||||
|
||||
completed_count = 0
|
||||
total_tasks = len(self.tasks) - 1
|
||||
logging.info(f"Need to complete {total_tasks} tasks (excluding manager task)")
|
||||
|
||||
while completed_count < total_tasks:
|
||||
tasks_summary = []
|
||||
for tid, tk in self.tasks.items():
|
||||
if tk.name == "manager_task":
|
||||
continue
|
||||
task_info = {
|
||||
"task_id": tid,
|
||||
"name": tk.name,
|
||||
"description": tk.description,
|
||||
"status": tk.status if tk.status else "not started",
|
||||
"agent": tk.agent.name if tk.agent else "No agent"
|
||||
}
|
||||
tasks_summary.append(task_info)
|
||||
logging.info(f"Task {tid} status: {task_info}")
|
||||
|
||||
manager_prompt = f"""
|
||||
Here is the current status of all tasks except yours (manager_task):
|
||||
{tasks_summary}
|
||||
|
||||
Provide a JSON with the structure:
|
||||
{{
|
||||
"task_id": <int>,
|
||||
"agent_name": "<string>",
|
||||
"action": "<execute or stop>"
|
||||
}}
|
||||
"""
|
||||
|
||||
try:
|
||||
logging.info("Requesting manager instructions...")
|
||||
if manager_task.async_execution:
|
||||
manager_response = await client.beta.chat.completions.parse(
|
||||
model=self.manager_llm,
|
||||
messages=[
|
||||
{"role": "system", "content": manager_task.description},
|
||||
{"role": "user", "content": manager_prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format=ManagerInstructions
|
||||
)
|
||||
else:
|
||||
manager_response = client.beta.chat.completions.parse(
|
||||
model=self.manager_llm,
|
||||
messages=[
|
||||
{"role": "system", "content": manager_task.description},
|
||||
{"role": "user", "content": manager_prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format=ManagerInstructions
|
||||
)
|
||||
parsed_instructions = manager_response.choices[0].message.parsed
|
||||
logging.info(f"Manager instructions: {parsed_instructions}")
|
||||
except Exception as e:
|
||||
display_error(f"Manager parse error: {e}")
|
||||
logging.error(f"Manager parse error: {str(e)}", exc_info=True)
|
||||
break
|
||||
|
||||
selected_task_id = parsed_instructions.task_id
|
||||
selected_agent_name = parsed_instructions.agent_name
|
||||
action = parsed_instructions.action
|
||||
|
||||
logging.info(f"Manager selected task_id={selected_task_id}, agent={selected_agent_name}, action={action}")
|
||||
|
||||
if action.lower() == "stop":
|
||||
logging.info("Manager decided to stop task execution")
|
||||
break
|
||||
|
||||
if selected_task_id not in self.tasks:
|
||||
error_msg = f"Manager selected invalid task id {selected_task_id}"
|
||||
display_error(error_msg)
|
||||
logging.error(error_msg)
|
||||
break
|
||||
|
||||
original_agent = self.tasks[selected_task_id].agent.name if self.tasks[selected_task_id].agent else "None"
|
||||
for a in self.agents:
|
||||
if a.name == selected_agent_name:
|
||||
self.tasks[selected_task_id].agent = a
|
||||
logging.info(f"Changed agent for task {selected_task_id} from {original_agent} to {selected_agent_name}")
|
||||
break
|
||||
|
||||
if self.tasks[selected_task_id].status != "completed":
|
||||
logging.info(f"Starting execution of task {selected_task_id}")
|
||||
yield selected_task_id
|
||||
logging.info(f"Finished execution of task {selected_task_id}, status: {self.tasks[selected_task_id].status}")
|
||||
|
||||
if self.tasks[selected_task_id].status == "completed":
|
||||
completed_count += 1
|
||||
logging.info(f"Task {selected_task_id} completed. Total completed: {completed_count}/{total_tasks}")
|
||||
|
||||
self.tasks[manager_task.id].status = "completed"
|
||||
if self.verbose >= 1:
|
||||
logging.info("All tasks completed under manager supervision.")
|
||||
logging.info("Hierarchical task execution finished")
|
||||
|
||||
def workflow(self):
|
||||
"""Synchronous version of workflow method"""
|
||||
# Build workflow relationships first
|
||||
for task in self.tasks.values():
|
||||
if task.next_tasks:
|
||||
@@ -145,11 +414,13 @@ Return a JSON object with an 'items' array containing the items to process.
|
||||
break
|
||||
|
||||
def sequential(self):
|
||||
"""Synchronous version of sequential method"""
|
||||
for task_id in self.tasks:
|
||||
if self.tasks[task_id].status != "completed":
|
||||
yield task_id
|
||||
|
||||
def hierarchical(self):
|
||||
"""Synchronous version of hierarchical method"""
|
||||
logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
|
||||
manager_agent = Agent(
|
||||
name="Manager",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import logging
|
||||
from typing import List, Optional, Dict, Any, Type, Callable, Union
|
||||
import asyncio
|
||||
from typing import List, Optional, Dict, Any, Type, Callable, Union, Coroutine
|
||||
from pydantic import BaseModel
|
||||
from ..main import TaskOutput
|
||||
from ..agent.agent import Agent
|
||||
@@ -19,7 +20,7 @@ class Task:
|
||||
output_file: Optional[str] = None,
|
||||
output_json: Optional[Type[BaseModel]] = None,
|
||||
output_pydantic: Optional[Type[BaseModel]] = None,
|
||||
callback: Optional[Any] = None,
|
||||
callback: Optional[Union[Callable[[TaskOutput], Any], Callable[[TaskOutput], Coroutine[Any, Any, Any]]]] = None,
|
||||
status: str = "not started",
|
||||
result: Optional[TaskOutput] = None,
|
||||
create_directory: Optional[bool] = False,
|
||||
@@ -61,4 +62,13 @@ class Task:
|
||||
self.previous_tasks = []
|
||||
|
||||
def __str__(self):
|
||||
return f"Task(name='{self.name if self.name else 'None'}', description='{self.description}', agent='{self.agent.name if self.agent else 'None'}', status='{self.status}')"
|
||||
return f"Task(name='{self.name if self.name else 'None'}', description='{self.description}', agent='{self.agent.name if self.agent else 'None'}', status='{self.status}')"
|
||||
|
||||
async def execute_callback(self, task_output: TaskOutput) -> None:
|
||||
"""Execute the callback function, handling both sync and async callbacks"""
|
||||
if self.callback:
|
||||
if asyncio.iscoroutinefunction(self.callback):
|
||||
await self.callback(task_output)
|
||||
else:
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, self.callback, task_output)
|
||||
@@ -0,0 +1,4 @@
|
||||
"""Tools package for PraisonAI Agents"""
|
||||
from .tools import Tools
|
||||
|
||||
__all__ = ['Tools']
|
||||
@@ -0,0 +1,40 @@
|
||||
"""Tools module for PraisonAI Agents"""
|
||||
from typing import List, Dict
|
||||
import logging
|
||||
import importlib
|
||||
|
||||
class Tools:
|
||||
@staticmethod
|
||||
def internet_search(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles, URLs, and snippets.
|
||||
"""
|
||||
# Check if duckduckgo_search is installed
|
||||
if importlib.util.find_spec("duckduckgo_search") is None:
|
||||
error_msg = "DuckDuckGo search is not available. Please install duckduckgo_search package using: pip install duckduckgo_search"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
|
||||
try:
|
||||
# Import only when needed
|
||||
from duckduckgo_search import DDGS
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error during DuckDuckGo search: {e}"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.16"
|
||||
version = "0.0.23"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
authors = [
|
||||
{ name="Mervin Praison" }
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Tools
|
||||
from pydantic import BaseModel
|
||||
|
||||
class AnalysisReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
|
||||
# Create a researcher agent
|
||||
researcher = Agent(
|
||||
name="AIResearcher",
|
||||
role="Technology Research Analyst",
|
||||
goal="Analyze and structure information about AI developments",
|
||||
backstory="Expert analyst specializing in AI technology trends",
|
||||
verbose=True,
|
||||
llm="gpt-4o-mini",
|
||||
tools=[Tools.internet_search],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create an analyst agent
|
||||
analyst = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Insights Specialist",
|
||||
goal="Structure and analyze research findings",
|
||||
backstory="Senior data analyst with expertise in pattern recognition",
|
||||
verbose=True,
|
||||
llm="gpt-4o-mini",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define structured tasks
|
||||
research_task = Task(
|
||||
name="gather_research",
|
||||
description="Research recent AI developments in 2024",
|
||||
agent=researcher,
|
||||
expected_output="Research findings"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
name="analyze_findings",
|
||||
description="Analyze research findings and create structured report. No additional text or explanation.",
|
||||
agent=analyst,
|
||||
output_json=AnalysisReport,
|
||||
expected_output="JSON object"
|
||||
)
|
||||
|
||||
# Initialize and run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, analyst],
|
||||
tasks=[research_task, analysis_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
result = agents.start()
|
||||
print(result)
|
||||
@@ -186,7 +186,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.16"
|
||||
version = "0.0.23"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
@@ -304,7 +304,7 @@ name = "tqdm"
|
||||
version = "4.67.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 }
|
||||
wheels = [
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
# Welcome to Praison AI! 🚀🤖
|
||||
@@ -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.20 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.32 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -45,6 +45,35 @@ The main class representing an AI agent with specific role, goal, and capabiliti
|
||||
|
||||
#### Methods
|
||||
- `chat(self, prompt, temperature=0.2, tools=None, output_json=None)` - Chat with the agent
|
||||
- `achat(self, prompt, temperature=0.2, tools=None, output_json=None)` - Async version of chat method
|
||||
- `clean_json_output(self, output: str) → str` - Clean and extract JSON from response text
|
||||
- `clear_history(self)` - Clear chat history
|
||||
- `execute_tool(self, function_name, arguments)` - Execute a tool dynamically based on the function name and arguments
|
||||
- `execute_tool(self, function_name, arguments)` - Execute a tool dynamically based on the function name and arguments
|
||||
- `_achat_completion(self, response, tools)` - Async version of _chat_completion method
|
||||
|
||||
#### Async Support
|
||||
The Agent class provides async support through the following methods:
|
||||
|
||||
- `achat`: Async version of the chat method for non-blocking communication
|
||||
- `_achat_completion`: Internal async method for handling chat completions
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
async def main():
|
||||
agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Async Specialist",
|
||||
goal="Handle async operations",
|
||||
backstory="Expert in async processing"
|
||||
)
|
||||
|
||||
# Use async chat
|
||||
result = await agent.achat(
|
||||
prompt="Your prompt here",
|
||||
tools=your_tools,
|
||||
output_json=your_schema
|
||||
)
|
||||
print(result)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
@@ -24,16 +24,16 @@ A Pydantic model for handling loop items.
|
||||
- `model_config` - Model configuration
|
||||
|
||||
### PraisonAIAgents
|
||||
The main class for managing AI agents and their tasks.
|
||||
The main class for managing agents and tasks execution.
|
||||
|
||||
#### Parameters
|
||||
- `agents` - List of agents
|
||||
- `tasks` - List of tasks
|
||||
- `verbose=0` - Verbosity level
|
||||
- `completion_checker=None` - Custom completion checker
|
||||
- `max_retries=5` - Maximum retry attempts
|
||||
- `process='sequential'` - Process execution mode
|
||||
- `manager_llm=None` - Manager language model
|
||||
- `agents: List[Agent]` - List of agents
|
||||
- `tasks: List[Task]` - List of tasks
|
||||
- `verbose: int = 0` - Verbosity level
|
||||
- `completion_checker: Optional[Callable] = None` - Custom completion checker
|
||||
- `max_retries: int = 5` - Maximum retry attempts
|
||||
- `process: str = "sequential"` - Process type (sequential, workflow, hierarchical)
|
||||
- `manager_llm: Optional[str] = None` - Language model for manager agent
|
||||
|
||||
#### Methods
|
||||
- `add_task(self, task)` - Add a task to the crew
|
||||
@@ -52,4 +52,62 @@ The main class for managing AI agents and their tasks.
|
||||
- `save_output_to_file(self, task, task_output)` - Save task output to file
|
||||
- `set_state(self, key: str, value: Any) → None` - Set a state value
|
||||
- `start(self)` - Start the crew execution
|
||||
- `update_state(self, updates: Dict) → None` - Update multiple state values
|
||||
- `update_state(self, updates: Dict) → None` - Update multiple state values
|
||||
|
||||
#### Async Methods
|
||||
- `astart(self)` - Async version of start method
|
||||
- `aexecute_task(self, task_id)` - Async version of execute_task
|
||||
- `arun_task(self, task_id)` - Async version of run_task
|
||||
- `arun_all_tasks(self)` - Async version of run_all_tasks
|
||||
|
||||
#### Async Support
|
||||
The PraisonAIAgents class provides comprehensive async support through the following methods:
|
||||
|
||||
```python
|
||||
class PraisonAIAgents:
|
||||
async def astart(self):
|
||||
"""Async version of start method"""
|
||||
await self.arun_all_tasks()
|
||||
return {
|
||||
"task_status": self.get_all_tasks_status(),
|
||||
"task_results": self.get_task_results()
|
||||
}
|
||||
|
||||
async def aexecute_task(self, task_id):
|
||||
"""Async version of execute_task method"""
|
||||
# Async task execution implementation
|
||||
|
||||
async def arun_task(self, task_id):
|
||||
"""Async version of run_task method"""
|
||||
# Async task running with retries
|
||||
|
||||
async def arun_all_tasks(self):
|
||||
"""Async version of run_all_tasks method"""
|
||||
# Async execution of all tasks
|
||||
```
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
async def main():
|
||||
# Initialize agents and tasks
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent1, async_agent2],
|
||||
tasks=[async_task1, async_task2],
|
||||
process="workflow"
|
||||
)
|
||||
|
||||
# Start async execution
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the async workflow
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
#### Async Features
|
||||
- Full async/await support
|
||||
- Parallel task execution
|
||||
- Non-blocking operations
|
||||
- Efficient resource utilization
|
||||
- Mixed sync/async task handling
|
||||
- Async process management
|
||||
@@ -4,143 +4,49 @@ description: "Praison AI Agents - SDK Documentation"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agent" icon="user" href="/api/praisonaiagents/agent/agent">
|
||||
Documentation for individual AI agents and their capabilities
|
||||
</Card>
|
||||
<Card title="Agents" icon="users" href="/api/praisonaiagents/agents/agents">
|
||||
Documentation for managing multiple agents and their interactions
|
||||
</Card>
|
||||
<Card title="Task" icon="list-check" href="/api/praisonaiagents/task/task">
|
||||
Documentation for defining and managing tasks
|
||||
</Card>
|
||||
<Card title="Process" icon="diagram-project" href="/api/praisonaiagents/process/process">
|
||||
Documentation for handling task execution flows
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
# Module praisonaiagents
|
||||
|
||||
## Sub-modules
|
||||
* praisonaiagents.agent
|
||||
* praisonaiagents.agents
|
||||
* praisonaiagents.main
|
||||
* praisonaiagents.task
|
||||
* praisonaiagents.agent - Agent module for defining individual AI agents
|
||||
* praisonaiagents.agents - Agents module for managing multiple agents
|
||||
* praisonaiagents.task - Task module for defining and managing tasks
|
||||
* praisonaiagents.process - Process module for handling task execution flows
|
||||
* praisonaiagents.main - Main module containing utility functions
|
||||
|
||||
## Functions
|
||||
|
||||
clean_triple_backticks(text: str) → str
|
||||
### clean_triple_backticks(text: str) → str
|
||||
Clean triple backticks from text output.
|
||||
|
||||
display_error(message: str, console=None)
|
||||
### display_error(message: str, console=None)
|
||||
Display error messages in the console.
|
||||
|
||||
display_generating(content: str = '', start_time: float | None = None)
|
||||
### display_generating(content: str = '', start_time: float | None = None)
|
||||
Display generation status with optional timing information.
|
||||
|
||||
display_instruction(message: str, console=None)
|
||||
### display_instruction(message: str, console=None)
|
||||
Display instruction messages in the console.
|
||||
|
||||
display_interaction(message, response, markdown=True, generation_time=None, console=None)
|
||||
### display_interaction(message, response, markdown=True, generation_time=None, console=None)
|
||||
Display interaction between user and agent.
|
||||
|
||||
display_self_reflection(message: str, console=None)
|
||||
### display_self_reflection(message: str, console=None)
|
||||
Display agent self-reflection messages.
|
||||
|
||||
display_tool_call(message: str, console=None)
|
||||
|
||||
## Classes
|
||||
|
||||
### Agent
|
||||
The Agent class represents an AI agent with specific role, goal, and capabilities.
|
||||
|
||||
#### Parameters
|
||||
- `name: str` - Name of the agent
|
||||
- `role: str` - Role of the agent
|
||||
- `goal: str` - Goal the agent aims to achieve
|
||||
- `backstory: str` - Background story of the agent
|
||||
- `llm: str | Any | None = 'gpt-4o'` - Language model to use
|
||||
- `tools: List[Any] | None = None` - List of tools available to the agent
|
||||
- `function_calling_llm: Any | None = None` - LLM for function calling
|
||||
- `max_iter: int = 20` - Maximum iterations
|
||||
- `max_rpm: int | None = None` - Maximum requests per minute
|
||||
- `max_execution_time: int | None = None` - Maximum execution time
|
||||
- `memory: bool = True` - Enable memory
|
||||
- `verbose: bool = True` - Enable verbose output
|
||||
- `allow_delegation: bool = False` - Allow task delegation
|
||||
- `step_callback: Any | None = None` - Callback for each step
|
||||
- `cache: bool = True` - Enable caching
|
||||
- `system_template: str | None = None` - System prompt template
|
||||
- `prompt_template: str | None = None` - Prompt template
|
||||
- `response_template: str | None = None` - Response template
|
||||
- `allow_code_execution: bool | None = False` - Allow code execution
|
||||
- `max_retry_limit: int = 2` - Maximum retry attempts
|
||||
- `respect_context_window: bool = True` - Respect context window size
|
||||
- `code_execution_mode: Literal['safe', 'unsafe'] = 'safe'` - Code execution mode
|
||||
- `embedder_config: Dict[str, Any] | None = None` - Embedder configuration
|
||||
- `knowledge_sources: List[Any] | None = None` - Knowledge sources
|
||||
- `use_system_prompt: bool | None = True` - Use system prompt
|
||||
- `markdown: bool = True` - Enable markdown
|
||||
- `self_reflect: bool = True` - Enable self reflection
|
||||
- `max_reflect: int = 3` - Maximum reflections
|
||||
- `min_reflect: int = 1` - Minimum reflections
|
||||
- `reflect_llm: str | None = None` - LLM for reflection
|
||||
|
||||
#### Methods
|
||||
- `chat(self, prompt, temperature=0.2, tools=None, output_json=None)`
|
||||
- `clean_json_output(self, output: str) → str` - Clean and extract JSON from response text
|
||||
- `clear_history(self)`
|
||||
- `execute_tool(self, function_name, arguments)` - Execute a tool dynamically
|
||||
|
||||
### PraisonAIAgents
|
||||
The main class for managing AI agents and their tasks.
|
||||
|
||||
#### Methods
|
||||
- `add_task(self, task)`
|
||||
- `clean_json_output(self, output: str)`
|
||||
- `clear_state(self) → None` - Clear all state values
|
||||
- `default_completion_checker(self, task, agent_output)`
|
||||
- `execute_task(self, task_id)`
|
||||
- `get_agent_details(self, agent_name)`
|
||||
- `get_all_tasks_status(self)`
|
||||
- `get_state(self, key: str, default: Any = None) → Any`
|
||||
- `get_task_details(self, task_id)`
|
||||
- `get_task_result(self, task_id)`
|
||||
- `get_task_status(self, task_id)`
|
||||
- `run_all_tasks(self)` - Execute tasks based on execution mode
|
||||
- `run_task(self, task_id)`
|
||||
- `save_output_to_file(self, task, task_output)`
|
||||
- `set_state(self, key: str, value: Any) → None`
|
||||
- `start(self)`
|
||||
- `update_state(self, updates: Dict) → None`
|
||||
|
||||
### ReflectionOutput
|
||||
A Pydantic model for reflection output.
|
||||
|
||||
#### Class Variables
|
||||
- `model_config`
|
||||
- `reflection: str`
|
||||
- `satisfactory: Literal['yes', 'no']`
|
||||
|
||||
### Task
|
||||
Represents a task to be executed by an agent.
|
||||
|
||||
#### Parameters
|
||||
- `description: str` - Task description
|
||||
- `expected_output: str` - Expected output description
|
||||
- `agent: Agent | None = None` - Agent assigned to the task
|
||||
- `name: str | None = None` - Task name
|
||||
- `tools: List[Any] | None = None` - Tools available for the task
|
||||
- `context: List[Task] | None = None` - Context from other tasks
|
||||
- `async_execution: bool | None = False` - Enable async execution
|
||||
- `config: Dict[str, Any] | None = None` - Task configuration
|
||||
- `output_file: str | None = None` - Output file path
|
||||
- `output_json: Type[BaseModel] | None = None` - JSON output schema
|
||||
- `output_pydantic: Type[BaseModel] | None = None` - Pydantic output schema
|
||||
- `callback: Any | None = None` - Task callback
|
||||
- `status: str = 'not started'` - Task status
|
||||
- `result: TaskOutput | None = None` - Task result
|
||||
- `create_directory: bool | None = False` - Create output directory
|
||||
- `id: int | None = None` - Task ID
|
||||
- `images: List[str] | None = None` - Task images
|
||||
- `next_tasks: List[str] | None = None` - Next tasks
|
||||
- `task_type: str = 'task'` - Task type
|
||||
- `condition: Dict[str, List[str]] | None = None` - Task conditions
|
||||
- `is_start: bool = False` - Is start task
|
||||
- `loop_state: Dict[str, str | int] | None = None` - Loop state
|
||||
|
||||
### TaskOutput
|
||||
A Pydantic model for task output.
|
||||
|
||||
#### Class Variables
|
||||
- `agent: str`
|
||||
- `description: str`
|
||||
- `json_dict: Dict[str, Any] | None`
|
||||
- `model_config`
|
||||
- `output_format: Literal['RAW', 'JSON', 'Pydantic']`
|
||||
- `pydantic: BaseModel | None`
|
||||
- `raw: str`
|
||||
- `summary: str | None`
|
||||
|
||||
#### Methods
|
||||
- `json(self) → str | None`
|
||||
- `to_dict(self) → dict`
|
||||
### display_tool_call(message: str, console=None)
|
||||
Display tool call messages.
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: "Process Module"
|
||||
description: "Documentation for the praisonaiagents.process.process module"
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
# Module praisonaiagents.process.process
|
||||
|
||||
## Classes
|
||||
|
||||
### Process
|
||||
The main class for handling task execution processes in different modes (sequential, hierarchical, workflow).
|
||||
|
||||
#### Parameters
|
||||
- `tasks: Dict[str, Task]` - Dictionary of tasks to be executed
|
||||
- `agents: List[Agent]` - List of available agents
|
||||
- `manager_llm: Optional[str] = None` - Language model for manager agent in hierarchical process
|
||||
- `verbose: bool = False` - Enable verbose logging
|
||||
|
||||
#### Methods
|
||||
- `workflow(self)` - Execute tasks in a workflow pattern with support for loops and conditions
|
||||
- `sequential(self)` - Execute tasks in sequential order
|
||||
- `hierarchical(self)` - Execute tasks in hierarchical order with a manager agent
|
||||
|
||||
#### Async Methods
|
||||
- `aworkflow(self) -> AsyncGenerator[str, None]` - Async version of workflow process
|
||||
- `asequential(self) -> AsyncGenerator[str, None]` - Async version of sequential process
|
||||
- `ahierarchical(self) -> AsyncGenerator[str, None]` - Async version of hierarchical process
|
||||
|
||||
#### Async Process Support
|
||||
Each process type has an async counterpart that supports non-blocking execution:
|
||||
|
||||
```python
|
||||
class Process:
|
||||
async def aworkflow(self):
|
||||
"""Async workflow process execution"""
|
||||
# Async workflow implementation
|
||||
|
||||
async def asequential(self):
|
||||
"""Async sequential process execution"""
|
||||
# Async sequential implementation
|
||||
|
||||
async def ahierarchical(self):
|
||||
"""Async hierarchical process execution"""
|
||||
# Async hierarchical implementation
|
||||
```
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
# Create process instance
|
||||
process = Process(tasks=tasks, agents=agents)
|
||||
|
||||
# Use async workflow
|
||||
async for task_id in process.aworkflow():
|
||||
# Handle task execution
|
||||
if tasks[task_id].async_execution:
|
||||
await handle_async_task(task_id)
|
||||
else:
|
||||
handle_sync_task(task_id)
|
||||
```
|
||||
|
||||
#### Async Process Features
|
||||
- Non-blocking task execution
|
||||
- Parallel task processing
|
||||
- Mixed sync/async task support
|
||||
- Efficient resource utilization
|
||||
- Async manager coordination (hierarchical)
|
||||
- Dynamic task scheduling (workflow)
|
||||
|
||||
### LoopItems
|
||||
A Pydantic model for handling loop data in workflow process.
|
||||
|
||||
#### Parameters
|
||||
- `items: List[Any]` - List of items to be processed in a loop
|
||||
|
||||
## Process Types
|
||||
|
||||
### Sequential Process
|
||||
- Tasks are executed one after another in a linear fashion
|
||||
- Each task is completed before moving to the next one
|
||||
- Simplest form of task execution
|
||||
|
||||
### Hierarchical Process
|
||||
- Uses a manager agent to coordinate task execution
|
||||
- Manager decides task order and agent assignments
|
||||
- Provides more complex task orchestration
|
||||
- Requires manager_llm parameter
|
||||
- Supports dynamic agent assignment
|
||||
|
||||
### Workflow Process
|
||||
- Supports complex task relationships
|
||||
- Features:
|
||||
- Task dependencies
|
||||
- Conditional execution
|
||||
- Loops
|
||||
- Context sharing between tasks
|
||||
- Maintains task state and relationships
|
||||
- Handles data flow between tasks
|
||||
@@ -33,4 +33,46 @@ Represents a task to be executed by an agent.
|
||||
- `task_type: str = 'task'` - Task type
|
||||
- `condition: Dict[str, List[str]] | None = None` - Task conditions
|
||||
- `is_start: bool = False` - Is start task
|
||||
- `loop_state: Dict[str, str | int] | None = None` - Loop state
|
||||
- `loop_state: Dict[str, str | int] | None = None` - Loop state
|
||||
|
||||
#### Async Support
|
||||
The Task class supports asynchronous execution through the following features:
|
||||
|
||||
- `async_execution`: Boolean flag to enable async execution
|
||||
- `callback`: Supports both sync and async callback functions
|
||||
- `execute_callback`: Internal async method for handling callbacks
|
||||
|
||||
Example usage:
|
||||
```python
|
||||
from typing import Coroutine
|
||||
from praisonaiagents import Task, TaskOutput
|
||||
|
||||
# Define an async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await some_async_operation()
|
||||
print(f"Processed: {output.raw}")
|
||||
|
||||
# Create task with async execution
|
||||
task = Task(
|
||||
description="Async task example",
|
||||
expected_output="Async result",
|
||||
async_execution=True, # Enable async execution
|
||||
callback=async_callback # Async callback
|
||||
)
|
||||
```
|
||||
|
||||
#### Callback Types
|
||||
The Task class supports both synchronous and asynchronous callbacks:
|
||||
```python
|
||||
# Type definition
|
||||
callback: Optional[Union[
|
||||
Callable[[TaskOutput], Any], # Sync callback
|
||||
Callable[[TaskOutput], Coroutine[Any, Any, Any]] # Async callback
|
||||
]]
|
||||
```
|
||||
|
||||
#### Async Task States
|
||||
- `not started`: Initial state
|
||||
- `in progress`: Task is being executed
|
||||
- `completed`: Task finished successfully
|
||||
- `failed`: Task execution failed
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Installation
|
||||
description: Set up PraisonAI in your development environment
|
||||
icon: download
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Requirements**
|
||||
|
||||
- Python 3.10 or higher
|
||||
- pip package manager
|
||||
- Virtual environment (recommended)
|
||||
</Note>
|
||||
|
||||
# Installing PraisonAI
|
||||
|
||||
Follow these steps to set up PraisonAI in your development environment.
|
||||
|
||||
<Steps>
|
||||
<Step title="Create Virtual Environment (Optional)">
|
||||
First, create and activate a virtual environment:
|
||||
<CodeGroup>
|
||||
```bash Mac/Linux
|
||||
python -m venv praisonai-env
|
||||
source praisonai-env/bin/activate
|
||||
```
|
||||
|
||||
```bash Windows
|
||||
python -m venv praisonai-env
|
||||
.\praisonai-env\Scripts\activate
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Install PraisonAI">
|
||||
Install the core package and tools:
|
||||
```bash Terminal
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Configure Environment">
|
||||
```bash Terminal
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys)
|
||||
You can also use other LLM providers like Anthropic, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Quick Start Guide"
|
||||
icon="bolt"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Build your first AI agent
|
||||
</Card>
|
||||
<Card
|
||||
title="API Reference"
|
||||
icon="code"
|
||||
href="/api/praisonaiagents/index"
|
||||
>
|
||||
Explore the API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: "Introduction"
|
||||
description: "Welcome to PraisonAI - The Next Generation AI Agent Framework"
|
||||
icon: "book-open"
|
||||
---
|
||||
|
||||
<Note>
|
||||
PraisonAI is a powerful framework for building and deploying AI agents that can understand, reason, and execute complex tasks autonomously.
|
||||
</Note>
|
||||
|
||||
# What is PraisonAI?
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Styling for main elements
|
||||
style Start fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Output fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Process fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[" "]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
|
||||
style Task1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon1 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
subgraph Agent2[" "]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
|
||||
style Task2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon2 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
%% Style for agent containers
|
||||
style Agent1 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
style Agent2 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Global styles
|
||||
classDef default fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
linkStyle default stroke:#7C90A0,stroke-width:2px
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agents" icon="user-robot">
|
||||
Autonomous AI entities that can understand context and execute tasks
|
||||
</Card>
|
||||
<Card title="Tasks" icon="list-check">
|
||||
Units of work that agents can execute independently or collaboratively
|
||||
</Card>
|
||||
<Card title="Process" icon="diagram-project">
|
||||
Workflow management for coordinating agent activities
|
||||
</Card>
|
||||
<Card title="Tools" icon="toolbox">
|
||||
Extensible capabilities that agents can leverage
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Key Features
|
||||
|
||||
<Steps>
|
||||
<Step title="Autonomous Agents">
|
||||
Create intelligent agents that can:
|
||||
- Understand natural language instructions
|
||||
- Make decisions based on context
|
||||
- Execute complex tasks autonomously
|
||||
</Step>
|
||||
<Step title="Flexible Architecture">
|
||||
Build with:
|
||||
- Modular components
|
||||
- Extensible tools
|
||||
- Customizable workflows
|
||||
</Step>
|
||||
<Step title="Advanced Capabilities">
|
||||
Leverage:
|
||||
- Multi-agent collaboration
|
||||
- Memory and context management
|
||||
- Tool integration
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Use Cases
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Customer Service" icon="headset">
|
||||
Build intelligent support agents that can handle customer inquiries and resolve issues autonomously.
|
||||
</Card>
|
||||
<Card title="Data Analysis" icon="chart-line">
|
||||
Create agents that can process, analyze, and derive insights from complex datasets.
|
||||
</Card>
|
||||
<Card title="Content Creation" icon="pen-nib">
|
||||
Deploy agents that can generate, edit, and optimize content across various formats.
|
||||
</Card>
|
||||
<Card title="Process Automation" icon="gears">
|
||||
Automate complex workflows with intelligent agents that can coordinate and execute tasks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Getting Started
|
||||
|
||||
<Warning>
|
||||
Before proceeding, ensure you have Python 3.9+ installed on your system.
|
||||
</Warning>
|
||||
|
||||
### Quick Setup
|
||||
|
||||
<CodeGroup>
|
||||
```bash pip
|
||||
pip install praisonai
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Basic Example
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Installation"
|
||||
icon="download"
|
||||
href="/code/installation"
|
||||
>
|
||||
Complete installation guide and setup instructions
|
||||
</Card>
|
||||
<Card
|
||||
title="Quick Start"
|
||||
icon="play"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Build your first AI agent in minutes
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Join our community on [Discord](https://www.youtube.com/redirect?event=channel_description&redir_token=QUFFLUhqbUpiZE00YlF1MjB1LVNIeTFxTnV6MWRRc18wZ3xBQ3Jtc0ttQVZ0aFJ4RXRDanlBQU1Vd3lHU3BBcml3bzhoek1pTmlkZkFkWjlNVDBpRkxZd1dTOWhPc20xbHJOb1NibmNYeTEydklJT0pZOVJFQW93MmJOQXU0WkJNVzNsd29SZ3FBNFVwMTFGNThNSHBWVUhjSQ&q=https%3A%2F%2Fdiscord.gg%2FnNZu5gGT59) to connect with other developers and get help!
|
||||
</Tip>
|
||||
@@ -0,0 +1,195 @@
|
||||
---
|
||||
title: Quick Start
|
||||
description: Build your first AI agent with PraisonAI
|
||||
icon: bolt
|
||||
---
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Install PraisonAI">
|
||||
Install the core package:
|
||||
```bash Terminal
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Configure Environment">
|
||||
```bash Terminal
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys)
|
||||
You can also use other LLM providers like Anthropic, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create `app.py`:
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create multiple agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="You are a content strategist",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Define multiple tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="Create a blog post about AI advancements",
|
||||
expected_output="A blog post",
|
||||
agent=writer
|
||||
)
|
||||
|
||||
# Run with hierarchical process
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
verbose=False,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Program">
|
||||
Execute your script:
|
||||
```bash Terminal
|
||||
python app.py
|
||||
```
|
||||
|
||||
You should see:
|
||||
- Agent initialization
|
||||
- Agents progress
|
||||
- Final results
|
||||
- Generated report
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Creating Custom Tool
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from duckduckgo_search import DDGS
|
||||
from typing import List, Dict
|
||||
|
||||
# 1. Tool
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform Internet Search
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
# 2. Agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 3. Tasks
|
||||
collect_task = Task(
|
||||
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
|
||||
expected_output="List of search results with titles, URLs, and snippets.",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
)
|
||||
|
||||
# 4. Start Agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[collect_task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Core Concepts"
|
||||
icon="book"
|
||||
href="/concepts/agents"
|
||||
>
|
||||
Learn about agents, tasks, and processes
|
||||
</Card>
|
||||
<Card
|
||||
title="API Reference"
|
||||
icon="code"
|
||||
href="/api/praisonaiagents/index"
|
||||
>
|
||||
Explore detailed API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,235 @@
|
||||
---
|
||||
title: "Agents"
|
||||
description: "Understanding Agents in PraisonAI"
|
||||
icon: "user"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Agents are the core building blocks of PraisonAI. Each agent is an autonomous AI entity with specific roles, goals, and capabilities.
|
||||
</Note>
|
||||
|
||||
# Understanding Agents
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Styling for main elements
|
||||
style Start fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Output fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style Process fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[" "]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
|
||||
style Task1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon1 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools1 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
subgraph Agent2[" "]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
|
||||
style Task2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
style AgentIcon2 fill:#5C80BC,stroke:#7C90A0,color:#fff
|
||||
style Tools2 fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
end
|
||||
|
||||
%% Style for agent containers
|
||||
style Agent1 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
style Agent2 fill:#1B1F3B,stroke:#7C90A0,color:#fff
|
||||
|
||||
%% Global styles
|
||||
classDef default fill:#2D3047,stroke:#7C90A0,color:#fff
|
||||
linkStyle default stroke:#7C90A0,stroke-width:2px
|
||||
```
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Role & Goal" icon="target">
|
||||
Defines the agent's purpose and objectives through role definition and specific goals
|
||||
</Card>
|
||||
<Card title="Capabilities" icon="toolbox">
|
||||
Tools and functions available to the agent for task execution
|
||||
</Card>
|
||||
<Card title="Memory" icon="brain">
|
||||
Context retention and learning capabilities across interactions
|
||||
</Card>
|
||||
<Card title="Language Model" icon="microchip">
|
||||
The underlying AI model powering the agent's intelligence
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Component Details
|
||||
|
||||
### Role and Goal
|
||||
<Tip>
|
||||
Clear role and goal definitions are crucial for optimal agent performance.
|
||||
</Tip>
|
||||
|
||||
| Component | Description | Example |
|
||||
|:----------|:------------|:--------|
|
||||
| **Role** | Agent's function and expertise | Research Analyst, Code Developer |
|
||||
| **Goal** | Specific objectives to achieve | Analyze market trends, Generate reports |
|
||||
| **Backstory** | Contextual background | Expert with 10 years of experience |
|
||||
|
||||
### Capabilities
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
agent = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Agent Types
|
||||
|
||||
<Steps>
|
||||
<Step title="Basic Agent">
|
||||
- Single-purpose focus
|
||||
- Direct user interaction
|
||||
- Limited tool set
|
||||
</Step>
|
||||
<Step title="Specialized Agent">
|
||||
- Domain expertise
|
||||
- Advanced capabilities
|
||||
- Custom tools
|
||||
</Step>
|
||||
<Step title="Collaborative Agent">
|
||||
- Team interaction
|
||||
- Task delegation
|
||||
- Shared context
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<Warning>
|
||||
Always implement proper error handling and resource management in your agent configurations.
|
||||
</Warning>
|
||||
|
||||
### Agent Design
|
||||
1. Clear role definition
|
||||
2. Specific, measurable goals
|
||||
3. Relevant tool selection
|
||||
4. Appropriate memory configuration
|
||||
|
||||
### Agent Interaction
|
||||
1. Clear communication protocols
|
||||
2. Defined delegation rules
|
||||
3. Error handling mechanisms
|
||||
4. Resource management
|
||||
|
||||
## Advanced Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Memory Management" icon="brain">
|
||||
- Short-term conversation memory
|
||||
- Long-term knowledge retention
|
||||
- Context preservation
|
||||
</Card>
|
||||
<Card title="Tool Integration" icon="plug">
|
||||
- Custom tool development
|
||||
- External API integration
|
||||
- Resource access control
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Async Support
|
||||
Agents now support asynchronous operations through the following methods:
|
||||
|
||||
- `achat`: Async version of the chat method
|
||||
- `astart`: Async version of start method
|
||||
- `aexecute_task`: Async version of execute_task method
|
||||
- `arun_task`: Async version of run_task method
|
||||
- `arun_all_tasks`: Async version of run_all_tasks method
|
||||
|
||||
### Example Usage:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
async def main():
|
||||
# Create an async agent
|
||||
async_agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Async Task Specialist",
|
||||
goal="Perform async operations",
|
||||
backstory="Expert in async operations",
|
||||
tools=[async_search_tool], # Your async tool
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create an async task
|
||||
async_task = Task(
|
||||
description="Perform async operation",
|
||||
expected_output="Async result",
|
||||
agent=async_agent,
|
||||
async_execution=True # Enable async execution
|
||||
)
|
||||
|
||||
# Create and start agents with async support
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Start async execution
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the async main function
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Key Features:
|
||||
- Full async/await support
|
||||
- Parallel task execution
|
||||
- Async tool integration
|
||||
- Async callback support
|
||||
- Mixed sync/async operations
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Create Your First Agent"
|
||||
icon="code"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Follow our quickstart guide to create your first agent
|
||||
</Card>
|
||||
<Card
|
||||
title="API Reference"
|
||||
icon="book"
|
||||
href="/api/praisonaiagents/agent/agent"
|
||||
>
|
||||
Explore the complete Agent API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,220 @@
|
||||
---
|
||||
title: "Process"
|
||||
description: "Understanding Process Types in PraisonAI"
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
# Understanding Process Types
|
||||
|
||||
Process types in PraisonAI define how tasks are executed and how agents collaborate. Each process type offers different patterns for task execution and agent coordination.
|
||||
|
||||
## Process Types Overview
|
||||
|
||||
Three types of processes are implemented in PraisonAI:
|
||||
|
||||
<Frame>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16m-7 6h7" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Sequential Process</h3>
|
||||
</div>
|
||||
<p>Linear task execution in a predefined order</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Hierarchical Process</h3>
|
||||
</div>
|
||||
<p>Manager-coordinated task execution with dynamic assignment</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-purple-600 dark:text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Workflow Process</h3>
|
||||
</div>
|
||||
<p>Complex task flows with conditional execution and state management</p>
|
||||
</div>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Sequential Process
|
||||
The simplest form of task execution where tasks are performed one after another.
|
||||
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
#### Characteristics
|
||||
- Linear execution flow
|
||||
- Predictable order
|
||||
- Simple dependency management
|
||||
- Direct task progression
|
||||
|
||||
#### Usage
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent1, agent2],
|
||||
tasks=[task1, task2, task3],
|
||||
process="sequential"
|
||||
)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Hierarchical Process
|
||||
Uses a manager agent to coordinate task execution and agent assignments.
|
||||
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
#### Characteristics
|
||||
- Manager-driven coordination
|
||||
- Dynamic task assignment
|
||||
- Flexible execution order
|
||||
- Intelligent resource allocation
|
||||
|
||||
#### Configuration
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[manager_agent, worker_agent1, worker_agent2],
|
||||
tasks=[task1, task2],
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Workflow Process
|
||||
Advanced process type supporting complex task relationships and conditional execution.
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/yWTH44QPl2A"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
#### Features
|
||||
- Task dependencies
|
||||
- Conditional branching
|
||||
- Loop handling
|
||||
- Context sharing
|
||||
- State management
|
||||
|
||||
#### Implementation
|
||||
```python
|
||||
task_workflow = {
|
||||
"start_task": {
|
||||
"next": ["decision_task"],
|
||||
"type": "task"
|
||||
},
|
||||
"decision_task": {
|
||||
"type": "decision",
|
||||
"conditions": {
|
||||
"success": ["process_task"],
|
||||
"failure": ["error_task"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### State Management
|
||||
- Task state tracking
|
||||
- Context preservation
|
||||
- Data flow control
|
||||
|
||||
### Error Handling
|
||||
- Graceful failure recovery
|
||||
- Alternative path execution
|
||||
- Error reporting
|
||||
|
||||
### Monitoring
|
||||
- Progress tracking
|
||||
- Performance metrics
|
||||
- Resource utilization
|
||||
|
||||
### Integration
|
||||
- External system coordination
|
||||
- API synchronization
|
||||
- Event handling
|
||||
|
||||
## Async Process Execution
|
||||
All process types (sequential, workflow, hierarchical) support async execution through async generators. This enables efficient handling of async tasks and parallel processing.
|
||||
|
||||
### Async Process Methods
|
||||
- `asequential`: Async version of sequential process
|
||||
- `aworkflow`: Async version of workflow process
|
||||
- `ahierarchical`: Async version of hierarchical process
|
||||
|
||||
### Example Usage:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
async def main():
|
||||
# Create agents and tasks
|
||||
agents = [async_agent1, async_agent2]
|
||||
tasks = [async_task1, async_task2]
|
||||
|
||||
# Initialize PraisonAIAgents with async workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=agents,
|
||||
tasks=tasks,
|
||||
process="workflow" # or "sequential" or "hierarchical"
|
||||
)
|
||||
|
||||
# Start async execution
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the async workflow
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Async Process Features:
|
||||
- Parallel task execution in workflow
|
||||
- Async task delegation in hierarchical process
|
||||
- Non-blocking task execution
|
||||
- Efficient resource utilization
|
||||
- Mixed sync/async task support
|
||||
|
||||
### Process-Specific Async Behavior:
|
||||
1. **Sequential Process**:
|
||||
- Tasks are executed in order
|
||||
- Async tasks don't block other tasks
|
||||
- Maintains sequential order while allowing async execution
|
||||
|
||||
2. **Workflow Process**:
|
||||
- Parallel execution of independent tasks
|
||||
- Async branching and merging
|
||||
- Dynamic task scheduling
|
||||
|
||||
3. **Hierarchical Process**:
|
||||
- Async manager delegation
|
||||
- Parallel subtask execution
|
||||
- Dynamic task assignment
|
||||
@@ -0,0 +1,317 @@
|
||||
---
|
||||
title: "Tasks"
|
||||
description: "Understanding Tasks in PraisonAI"
|
||||
icon: "list-check"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Tasks are the fundamental units of work in PraisonAI, defining what needs to be done, how it should be done, and who should do it.
|
||||
</Note>
|
||||
|
||||
# Understanding Tasks
|
||||
|
||||
<Frame>
|
||||
<div className="p-6 bg-white dark:bg-gray-800 rounded-lg">
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
{/* Task Flow Steps */}
|
||||
<div className="flex justify-between items-center">
|
||||
{/* Task Definition */}
|
||||
<div className="flex-1 p-4 border-2 border-blue-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Task Definition</h4>
|
||||
<p className="text-sm mt-1">Description & Requirements</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow 1 */}
|
||||
<div className="flex-none px-4">
|
||||
<svg className="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Agent Assignment */}
|
||||
<div className="flex-1 p-4 border-2 border-green-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Agent Assignment</h4>
|
||||
<p className="text-sm mt-1">Matching & Delegation</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow 2 */}
|
||||
<div className="flex-none px-4">
|
||||
<svg className="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Execution */}
|
||||
<div className="flex-1 p-4 border-2 border-purple-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-purple-600 dark:text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Execution</h4>
|
||||
<p className="text-sm mt-1">Processing & Tools</p>
|
||||
</div>
|
||||
|
||||
{/* Arrow 3 */}
|
||||
<div className="flex-none px-4">
|
||||
<svg className="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Output */}
|
||||
<div className="flex-1 p-4 border-2 border-yellow-500 rounded-lg text-center">
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="p-2 bg-yellow-100 dark:bg-yellow-900 rounded-full">
|
||||
<svg className="w-6 h-6 text-yellow-600 dark:text-yellow-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold">Output</h4>
|
||||
<p className="text-sm mt-1">Results & Validation</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Task States */}
|
||||
<div className="grid grid-cols-4 gap-4 mt-4">
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-blue-50 dark:bg-blue-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">Pending</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-yellow-50 dark:bg-yellow-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">In Progress</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-green-50 dark:bg-green-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">Completed</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3 border border-gray-200 rounded-lg bg-red-50 dark:bg-red-900">
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="font-semibold">Failed</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Core Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Task Definition" icon="file-lines">
|
||||
Clear description of work to be done and expected outputs
|
||||
</Card>
|
||||
<Card title="Agent Assignment" icon="user-check">
|
||||
Matching tasks with capable agents
|
||||
</Card>
|
||||
<Card title="Tool Access" icon="toolbox">
|
||||
Resources available for task completion
|
||||
</Card>
|
||||
<Card title="Output Handling" icon="file-export">
|
||||
Managing and formatting task results
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Task Configuration
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
task = Task(
|
||||
description="Research AI trends",
|
||||
expected_output="Summary report",
|
||||
agent=research_agent
|
||||
)
|
||||
```
|
||||
```python Advanced
|
||||
task = Task(
|
||||
description="Analyze market data",
|
||||
expected_output="Detailed analysis",
|
||||
agent=analyst_agent,
|
||||
tools=[AnalysisTool()],
|
||||
output_file="analysis.md",
|
||||
async_execution=True
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Task Types
|
||||
|
||||
<Steps>
|
||||
<Step title="Basic Task">
|
||||
Simple, single-operation tasks with clear inputs and outputs
|
||||
</Step>
|
||||
<Step title="Decision Task">
|
||||
Tasks involving choices and conditional paths
|
||||
```python
|
||||
decision_task = Task(
|
||||
type="decision",
|
||||
conditions={
|
||||
"success": ["next_task"],
|
||||
"failure": ["error_task"]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
<Step title="Loop Task">
|
||||
Repetitive operations over collections
|
||||
```python
|
||||
loop_task = Task(
|
||||
type="loop",
|
||||
items=data_list,
|
||||
operation="process_item"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Task Relationships
|
||||
|
||||
<Warning>
|
||||
Properly managing task dependencies is crucial for complex workflows. Always ensure proper context sharing and error handling.
|
||||
</Warning>
|
||||
|
||||
### Context Sharing
|
||||
```python
|
||||
task_a = Task(name="research")
|
||||
task_b = Task(
|
||||
name="analyze",
|
||||
context=[task_a] # Uses task_a's output
|
||||
)
|
||||
```
|
||||
|
||||
### Task Dependencies
|
||||
|
||||
| Relationship | Description | Example |
|
||||
|:-------------|:------------|:--------|
|
||||
| **Sequential** | Tasks run one after another | Research → Analysis → Report |
|
||||
| **Parallel** | Independent tasks run simultaneously | Data Collection + Processing |
|
||||
| **Conditional** | Tasks depend on previous results | Success → Next Task, Failure → Retry |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Output Handling" icon="file-code">
|
||||
- Multiple output formats
|
||||
- Structured data validation
|
||||
- File system integration
|
||||
</Card>
|
||||
<Card title="Task Control" icon="sliders">
|
||||
- Execution flow control
|
||||
- Error recovery
|
||||
- Progress tracking
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<Tip>
|
||||
Design tasks to be atomic and focused. Each task should have a single, clear responsibility.
|
||||
</Tip>
|
||||
|
||||
1. Clear task descriptions
|
||||
2. Well-defined success criteria
|
||||
3. Appropriate tool selection
|
||||
4. Error handling consideration
|
||||
5. Resource management
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Create Tasks"
|
||||
icon="plus"
|
||||
href="/code/quickstart"
|
||||
>
|
||||
Learn how to create and configure tasks
|
||||
</Card>
|
||||
<Card
|
||||
title="Task API"
|
||||
icon="code"
|
||||
href="/api/praisonaiagents/task/task"
|
||||
>
|
||||
Explore the complete Task API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Async Task Execution
|
||||
Tasks can be executed asynchronously by setting `async_execution=True`. This is particularly useful for tasks that involve I/O operations or when you want to run multiple tasks in parallel.
|
||||
|
||||
### Async Task Configuration
|
||||
```python
|
||||
async_task = Task(
|
||||
description="Perform async operation",
|
||||
expected_output="Async result",
|
||||
agent=async_agent,
|
||||
async_execution=True, # Enable async execution
|
||||
callback=async_callback # Optional async callback
|
||||
)
|
||||
```
|
||||
|
||||
### Async Callbacks
|
||||
Tasks support both synchronous and asynchronous callbacks:
|
||||
|
||||
```python
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate async operation
|
||||
print(f"Processed output: {output.raw}")
|
||||
|
||||
# Task with async callback
|
||||
task = Task(
|
||||
description="Task with async callback",
|
||||
expected_output="Result",
|
||||
agent=agent,
|
||||
async_execution=True,
|
||||
callback=async_callback
|
||||
)
|
||||
```
|
||||
|
||||
### Mixing Sync and Async Tasks
|
||||
You can mix synchronous and asynchronous tasks in the same workflow:
|
||||
|
||||
```python
|
||||
# Sync task
|
||||
sync_task = Task(
|
||||
description="Synchronous operation",
|
||||
expected_output="Sync result",
|
||||
agent=sync_agent,
|
||||
async_execution=False
|
||||
)
|
||||
|
||||
# Async task
|
||||
async_task = Task(
|
||||
description="Asynchronous operation",
|
||||
expected_output="Async result",
|
||||
agent=async_agent,
|
||||
async_execution=True
|
||||
)
|
||||
|
||||
# Create agents with mixed tasks
|
||||
agents = PraisonAIAgents(
|
||||
agents=[sync_agent, async_agent],
|
||||
tasks=[sync_task, async_task]
|
||||
)
|
||||
|
||||
# Run asynchronously
|
||||
result = await agents.astart()
|
||||
```
|
||||
@@ -0,0 +1,335 @@
|
||||
---
|
||||
title: "Tools"
|
||||
description: "Understanding Tools in PraisonAI"
|
||||
icon: "screwdriver-wrench"
|
||||
---
|
||||
|
||||
# Understanding Tools
|
||||
|
||||
Tools in PraisonAI are functions that agents can use to interact with external systems, perform computations, or access data. They extend the capabilities of agents beyond just language processing.
|
||||
|
||||
## Tools Overview
|
||||
|
||||
<Frame>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-blue-600 dark:text-blue-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">Search Tools</h3>
|
||||
</div>
|
||||
<p>Tools for searching and retrieving information from various sources</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">File Tools</h3>
|
||||
</div>
|
||||
<p>Tools for reading, writing, and manipulating files</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<div className="flex items-center mb-4">
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900 rounded-lg">
|
||||
<svg className="w-6 h-6 text-purple-600 dark:text-purple-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="ml-3 text-lg font-semibold">API Tools</h3>
|
||||
</div>
|
||||
<p>Tools for interacting with external APIs and services</p>
|
||||
</div>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Creating Custom Tool
|
||||
<Steps>
|
||||
<Step>
|
||||
Create any function that you want to use as a tool, that performs a specific task.
|
||||
```python
|
||||
from duckduckgo_search import DDGS
|
||||
from typing import List, Dict
|
||||
|
||||
# Tool Implementation
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform Internet Search using DuckDuckGo
|
||||
|
||||
Args:
|
||||
query (str): The search query string
|
||||
|
||||
Returns:
|
||||
List[Dict]: List of search results containing title, URL, and snippet
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
```
|
||||
</Step>
|
||||
<Step>
|
||||
Assign the tool to an agent
|
||||
```python
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool], ## Add the tool to the agent i.e the function name
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Card title="That's it!">
|
||||
<Check>You have created a custom tool and assigned it to an agent.</Check>
|
||||
</Card>
|
||||
|
||||
## Implementing Tools Full Code Example
|
||||
|
||||
Tools are implemented as Python functions with type hints and docstrings. Here's a complete example:
|
||||
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from duckduckgo_search import DDGS
|
||||
from typing import List, Dict
|
||||
|
||||
# 1. Tool Implementation
|
||||
def internet_search_tool(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform Internet Search using DuckDuckGo
|
||||
|
||||
Args:
|
||||
query (str): The search query string
|
||||
|
||||
Returns:
|
||||
List[Dict]: List of search results containing title, URL, and snippet
|
||||
"""
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
# 2. Assign the tool to an agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Search Specialist",
|
||||
goal="Perform internet searches to collect relevant information.",
|
||||
backstory="Expert in finding and organising internet data.",
|
||||
tools=[internet_search_tool],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# 3. Task Definition
|
||||
collect_task = Task(
|
||||
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
|
||||
expected_output="List of search results with titles, URLs, and snippets.",
|
||||
agent=data_agent,
|
||||
name="collect_data",
|
||||
)
|
||||
|
||||
# 4. Start Agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[collect_task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Advanced Tool Features
|
||||
|
||||
### Tool Configuration
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
def configured_tool(
|
||||
query: str,
|
||||
max_results: int = 5,
|
||||
timeout: int = 10
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
Example of a configurable tool
|
||||
|
||||
Args:
|
||||
query (str): Search query
|
||||
max_results (int): Maximum number of results
|
||||
timeout (int): Request timeout in seconds
|
||||
|
||||
Returns:
|
||||
List[Dict]: Search results
|
||||
"""
|
||||
# Tool implementation
|
||||
pass
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Tool Chaining
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
def chain_tools(input_data: str) -> Dict:
|
||||
"""
|
||||
Example of chaining multiple tools
|
||||
|
||||
Args:
|
||||
input_data (str): Input data
|
||||
|
||||
Returns:
|
||||
Dict: Processed results
|
||||
"""
|
||||
# 1. Search for data
|
||||
search_results = internet_search_tool(input_data)
|
||||
|
||||
# 2. Process results
|
||||
processed_data = process_tool(search_results)
|
||||
|
||||
# 3. Format output
|
||||
return format_tool(processed_data)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Tool Categories
|
||||
|
||||
1. **Data Collection Tools**
|
||||
- Web scraping
|
||||
- API integration
|
||||
- Database queries
|
||||
|
||||
2. **Processing Tools**
|
||||
- Data transformation
|
||||
- Text analysis
|
||||
- Image processing
|
||||
|
||||
3. **Output Tools**
|
||||
- File generation
|
||||
- Report creation
|
||||
- Data visualization
|
||||
|
||||
## Tool Integration
|
||||
|
||||
### Adding Tools to Agents
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
# Multiple tools
|
||||
agent = Agent(
|
||||
name="MultiTool Agent",
|
||||
tools=[
|
||||
internet_search_tool,
|
||||
file_processing_tool,
|
||||
api_integration_tool
|
||||
]
|
||||
)
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
### Tool Dependencies
|
||||
<Frame>
|
||||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg">
|
||||
```python
|
||||
# Tool with dependencies
|
||||
def advanced_tool(data: Dict) -> Dict:
|
||||
"""
|
||||
Tool that depends on external libraries
|
||||
|
||||
Args:
|
||||
data (Dict): Input data
|
||||
|
||||
Returns:
|
||||
Dict: Processed data
|
||||
"""
|
||||
try:
|
||||
import required_library
|
||||
# Tool implementation
|
||||
return processed_result
|
||||
except ImportError:
|
||||
raise Exception("Required library not installed")
|
||||
```
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Tool Guidelines
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-lg font-semibold mb-3">Best Practices</h3>
|
||||
1. **Type Hints**
|
||||
- Use Python type hints
|
||||
- Define clear input/output types
|
||||
- Document complex types
|
||||
|
||||
2. **Documentation**
|
||||
- Write clear docstrings
|
||||
- Explain parameters
|
||||
- Provide usage examples
|
||||
|
||||
3. **Error Handling**
|
||||
- Handle exceptions gracefully
|
||||
- Return meaningful errors
|
||||
- Validate inputs
|
||||
</div>
|
||||
|
||||
<div className="p-4 border rounded-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-lg font-semibold mb-3">Tool Types</h3>
|
||||
1. **Search Tools**
|
||||
- Web search
|
||||
- Database queries
|
||||
- Document search
|
||||
|
||||
2. **File Tools**
|
||||
- Read/write operations
|
||||
- File conversion
|
||||
- Data extraction
|
||||
|
||||
3. **API Tools**
|
||||
- REST API calls
|
||||
- GraphQL queries
|
||||
- Service integration
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Best Practices Summary
|
||||
|
||||
1. **Design Principles**
|
||||
- Single responsibility
|
||||
- Clear interfaces
|
||||
- Proper documentation
|
||||
- Error handling
|
||||
|
||||
2. **Performance**
|
||||
- Efficient processing
|
||||
- Resource management
|
||||
- Caching when appropriate
|
||||
- Asynchronous operations
|
||||
|
||||
3. **Security**
|
||||
- Input validation
|
||||
- Rate limiting
|
||||
- API key management
|
||||
- Error masking
|
||||
@@ -4,6 +4,19 @@ description: "Guide for using PraisonAI in Google Colab environments, with examp
|
||||
icon: "google"
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Basic PraisonAI" icon="book">
|
||||
<a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-googlecolab.ipynb">
|
||||
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" />
|
||||
</a>
|
||||
</Card>
|
||||
<Card title="PraisonAI with Tools" icon="screwdriver-wrench">
|
||||
<a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb">
|
||||
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" />
|
||||
</a>
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
```
|
||||
jupyter:
|
||||
accelerator: GPU
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
---
|
||||
title: "Async AI Agents"
|
||||
description: "Async AI Agents allow you to run AI tasks asynchronously, improving performance and efficiency in your applications."
|
||||
icon: "clock"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Requirements**
|
||||
|
||||
- Python 3.10 or higher
|
||||
- Basic understanding of async/await in Python
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your OpenAI API key as an environment variable:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key_here
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Project">
|
||||
Create a new file `app.py` with the basic setup:
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Assistant",
|
||||
goal="Help with tasks",
|
||||
backstory="Expert in async operations"
|
||||
)
|
||||
|
||||
# Create a task
|
||||
task = Task(
|
||||
name="hello_task",
|
||||
description="Say hello and introduce yourself",
|
||||
agent=agent,
|
||||
async_execution=True,
|
||||
expected_output="Answer to the question"
|
||||
)
|
||||
|
||||
# Create agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Main async function
|
||||
async def main():
|
||||
result = await agents.astart()
|
||||
print(result)
|
||||
|
||||
# Run the program
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Program">
|
||||
Run your async AI agent:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/VhVQfgo00LE"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Understanding Async Execution
|
||||
|
||||
<Card title="What is Asynchronous Execution?" icon="question">
|
||||
Async execution lets your program continue running while waiting for operations to complete. This is ideal for:
|
||||
- Making multiple AI API calls
|
||||
- Processing large datasets
|
||||
- Handling multiple tasks simultaneously
|
||||
- Maintaining responsive applications
|
||||
</Card>
|
||||
|
||||
<CodeGroup>
|
||||
```python Sync
|
||||
# Synchronous execution (blocks until complete)
|
||||
result = agent.chat("Hello")
|
||||
```
|
||||
|
||||
```python Async
|
||||
# Asynchronous execution (non-blocking)
|
||||
result = await agent.achat("Hello")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Async Tasks" icon="tasks">
|
||||
Create tasks that run asynchronously with built-in error handling and retries.
|
||||
</Card>
|
||||
<Card title="Parallel Processing" icon="arrows-split-up-and-left">
|
||||
Run multiple tasks in parallel using asyncio.gather().
|
||||
</Card>
|
||||
<Card title="Mixed Mode" icon="shuffle">
|
||||
Mix sync and async tasks in the same workflow seamlessly.
|
||||
</Card>
|
||||
<Card title="Resource Management" icon="gear">
|
||||
Built-in resource management and performance optimization.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Async Tasks with Callbacks and Tools Example Code
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
|
||||
from duckduckgo_search import DDGS
|
||||
from pydantic import BaseModel
|
||||
|
||||
# 1. Define async tool
|
||||
class SearchResult(BaseModel):
|
||||
query: str
|
||||
results: List[Dict[str, str]]
|
||||
total_results: int
|
||||
|
||||
async def async_search_tool(query: str) -> Dict:
|
||||
"""
|
||||
Asynchronous search using DuckDuckGo.
|
||||
Args:
|
||||
query (str): The search query.
|
||||
Returns:
|
||||
dict: Search results in SearchResult model format
|
||||
"""
|
||||
await asyncio.sleep(1) # Simulate network delay
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
|
||||
# Format response to match SearchResult model
|
||||
return {
|
||||
"query": query,
|
||||
"results": results,
|
||||
"total_results": len(results)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error during async search: {e}")
|
||||
return {
|
||||
"query": query,
|
||||
"results": [],
|
||||
"total_results": 0
|
||||
}
|
||||
|
||||
# 2. Define async callback
|
||||
async def async_callback(output: TaskOutput):
|
||||
await asyncio.sleep(1) # Simulate processing
|
||||
if output.output_format == "JSON":
|
||||
print(f"Processed JSON result: {output.json_dict}")
|
||||
elif output.output_format == "Pydantic":
|
||||
print(f"Processed Pydantic result: {output.pydantic}")
|
||||
|
||||
# 3. Create specialized agents
|
||||
async_agent = Agent(
|
||||
name="AsyncSearchAgent",
|
||||
role="Asynchronous Search Specialist",
|
||||
goal="Perform fast and efficient asynchronous searches with structured results",
|
||||
backstory="Expert in parallel search operations and data retrieval",
|
||||
tools=[async_search_tool],
|
||||
self_reflect=False,
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
summary_agent = Agent(
|
||||
name="SummaryAgent",
|
||||
role="Research Synthesizer",
|
||||
goal="Create comprehensive summaries and identify patterns across multiple search results",
|
||||
backstory="""Expert in analyzing and synthesizing information from multiple sources.
|
||||
Skilled at identifying patterns, trends, and connections between different topics.
|
||||
Specializes in creating clear, structured summaries that highlight key insights.""",
|
||||
self_reflect=True, # Enable self-reflection for better summary quality
|
||||
verbose=True,
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 4. Create async tasks
|
||||
async_task = Task(
|
||||
name="async_search",
|
||||
description="""Search for 'Async programming' and return results in the following JSON format:
|
||||
{
|
||||
"query": "the search query",
|
||||
"results": [
|
||||
{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}
|
||||
],
|
||||
"total_results": number of results
|
||||
}""",
|
||||
expected_output="SearchResult model with query details and results",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_pydantic=SearchResult
|
||||
)
|
||||
|
||||
# 5. Example usage functions
|
||||
async def run_single_task():
|
||||
"""Run single async task"""
|
||||
print("\nRunning Single Async Task...")
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent],
|
||||
tasks=[async_task],
|
||||
verbose=1,
|
||||
process="sequential"
|
||||
)
|
||||
result = await agents.astart()
|
||||
print(f"Single Task Result: {result}")
|
||||
|
||||
async def run_parallel_tasks():
|
||||
"""Run multiple async tasks in parallel"""
|
||||
print("\nRunning Parallel Async Tasks...")
|
||||
|
||||
# Define different search topics
|
||||
search_topics = [
|
||||
"Latest AI Developments 2024",
|
||||
"Machine Learning Best Practices",
|
||||
"Neural Networks Architecture"
|
||||
]
|
||||
|
||||
# Create tasks for different topics
|
||||
parallel_tasks = [
|
||||
Task(
|
||||
name=f"search_task_{i}",
|
||||
description=f"""Search for '{topic}' and return results in the following JSON format:
|
||||
{{
|
||||
"query": "{topic}",
|
||||
"results": [
|
||||
{{
|
||||
"title": "result title",
|
||||
"url": "result url",
|
||||
"snippet": "result snippet"
|
||||
}}
|
||||
],
|
||||
"total_results": number of results
|
||||
}}""",
|
||||
expected_output="SearchResult model with detailed information",
|
||||
agent=async_agent,
|
||||
async_execution=True,
|
||||
callback=async_callback,
|
||||
output_pydantic=SearchResult
|
||||
) for i, topic in enumerate(search_topics)
|
||||
]
|
||||
|
||||
# Create summarization task with the specialized summary agent
|
||||
summary_task = Task(
|
||||
name="summary_task",
|
||||
description="""As a Research Synthesizer, analyze the search results and create a comprehensive summary. Your task:
|
||||
|
||||
1. Analyze Results:
|
||||
- Review all search results thoroughly
|
||||
- Extract key findings from each topic
|
||||
- Identify main themes and concepts
|
||||
|
||||
2. Find Connections:
|
||||
- Identify relationships between topics
|
||||
- Spot common patterns or contradictions
|
||||
- Note emerging trends across sources
|
||||
|
||||
3. Create Structured Summary:
|
||||
- Main findings per topic
|
||||
- Cross-cutting themes
|
||||
- Emerging trends
|
||||
- Practical implications
|
||||
- Future directions
|
||||
|
||||
4. Quality Checks:
|
||||
- Ensure all topics are covered
|
||||
- Verify accuracy of connections
|
||||
- Confirm clarity of insights
|
||||
- Validate practical relevance
|
||||
|
||||
Present the summary in a clear, structured format with sections for findings, patterns, trends, and implications.""",
|
||||
expected_output="""A comprehensive research synthesis containing:
|
||||
- Detailed findings from each search topic
|
||||
- Cross-topic patterns and relationships
|
||||
- Emerging trends and their implications
|
||||
- Practical applications and future directions""",
|
||||
agent=summary_agent, # Use the specialized summary agent
|
||||
async_execution=False, # Run synchronously after search tasks
|
||||
callback=async_callback
|
||||
)
|
||||
|
||||
# Create a single PraisonAIAgents instance with both agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[async_agent, summary_agent], # Include both agents
|
||||
tasks=parallel_tasks + [summary_task], # Include all tasks
|
||||
verbose=1,
|
||||
process="sequential" # Tasks will run in sequence, with parallel tasks running first
|
||||
)
|
||||
|
||||
# Run all tasks
|
||||
results = await agents.astart()
|
||||
print(f"Tasks Results: {results}")
|
||||
|
||||
# Return results in a serializable format
|
||||
return {
|
||||
"search_results": {
|
||||
"task_status": {k: v for k, v in results["task_status"].items() if k != summary_task.id},
|
||||
"task_results": [str(results["task_results"][i]) if results["task_results"][i] else None
|
||||
for i in range(len(parallel_tasks))]
|
||||
},
|
||||
"summary": str(results["task_results"][summary_task.id]) if results["task_results"].get(summary_task.id) else None,
|
||||
"topics": search_topics
|
||||
}
|
||||
|
||||
# 6. Main execution
|
||||
async def main():
|
||||
"""Main execution function"""
|
||||
print("Starting Async AI Agents Examples...")
|
||||
|
||||
try:
|
||||
# Run different async patterns
|
||||
await run_single_task()
|
||||
await run_parallel_tasks()
|
||||
except Exception as e:
|
||||
print(f"Error in main execution: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the main function
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
### 1. Async Tasks with Callbacks
|
||||
|
||||
<CodeGroup>
|
||||
```python Task
|
||||
# Create an async task with callback
|
||||
async_task = Task(
|
||||
name="weather_task",
|
||||
description="Check weather conditions",
|
||||
agent=agent,
|
||||
async_execution=True,
|
||||
callback=async_callback
|
||||
)
|
||||
```
|
||||
|
||||
```python Callback
|
||||
async def async_callback(output):
|
||||
await process_result(output)
|
||||
await save_to_database(output)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Parallel Task Processing
|
||||
|
||||
<Warning>
|
||||
Be mindful of rate limits and resource usage when processing tasks in parallel.
|
||||
</Warning>
|
||||
|
||||
```python
|
||||
async def process_multiple_tasks():
|
||||
tasks = [
|
||||
Task(
|
||||
name=f"task_{i}",
|
||||
description=f"Process item {i}",
|
||||
async_execution=True
|
||||
) for i in range(5)
|
||||
]
|
||||
|
||||
results = await asyncio.gather(
|
||||
*[agent.achat(task.description) for task in tasks]
|
||||
)
|
||||
return results
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error Handling">
|
||||
```python
|
||||
async def safe_async_operation():
|
||||
try:
|
||||
result = await agent.achat("Process this")
|
||||
return result
|
||||
except Exception as e:
|
||||
logging.error(f"Error: {e}")
|
||||
return None
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Resource Management">
|
||||
```python
|
||||
async def efficient_processing():
|
||||
semaphore = asyncio.Semaphore(5)
|
||||
async with semaphore:
|
||||
result = await agent.achat("Process within limits")
|
||||
return result
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Performance Tips">
|
||||
- Use `asyncio.gather()` for parallel operations
|
||||
- Implement proper error handling
|
||||
- Monitor memory usage
|
||||
- Use timeouts for long-running operations
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="ChatCompletion Error" icon="triangle-exclamation">
|
||||
If you see "ChatCompletion can't be used in await expression":
|
||||
- Use AsyncOpenAI() client
|
||||
- Ensure proper async context
|
||||
</Card>
|
||||
|
||||
<Card title="Event Loop Error" icon="circle-exclamation">
|
||||
If you get "Event loop is closed":
|
||||
- Use asyncio.run() for main entry
|
||||
- Check async context
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## API Reference
|
||||
|
||||
### Async Methods
|
||||
|
||||
<ResponseField name="achat()" type="async">
|
||||
Async version of chat method
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="aexecute_tool()" type="async">
|
||||
Async tool execution method
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="astart()" type="async">
|
||||
Async task execution starter
|
||||
</ResponseField>
|
||||
|
||||
### Task Properties
|
||||
|
||||
<ResponseField name="async_execution" type="boolean">
|
||||
Enable/disable async mode for tasks
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="callback" type="function">
|
||||
Set sync or async callback function
|
||||
</ResponseField>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Examples" icon="code" href="./examples">
|
||||
Check out more examples in our examples directory
|
||||
</Card>
|
||||
<Card title="Advanced Topics" icon="book" href="./advanced">
|
||||
Learn about advanced async patterns and optimizations
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Remember to handle errors properly, manage resources efficiently, and test thoroughly in async contexts.
|
||||
</Note>
|
||||
@@ -0,0 +1,783 @@
|
||||
---
|
||||
title: "AI Agents with Callbacks"
|
||||
sidebarTitle: "Callbacks"
|
||||
description: "Learn how to implement callbacks to monitor and log AI agent interactions, errors, and task completions."
|
||||
icon: "bell"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of Python functions
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Required Functions">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import (
|
||||
register_display_callback,
|
||||
Agent,
|
||||
Task,
|
||||
PraisonAIAgents
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create a Simple Callback">
|
||||
Define your first callback function:
|
||||
```python
|
||||
def simple_callback(message=None, response=None, **kwargs):
|
||||
print(f"Received message: {message}")
|
||||
print(f"Got response: {response}")
|
||||
|
||||
# Register as synchronous callback
|
||||
register_display_callback('interaction', simple_callback, is_async=False)
|
||||
|
||||
# For async callbacks
|
||||
async def async_simple_callback(message=None, response=None, **kwargs):
|
||||
await asyncio.sleep(0) # Non-blocking pause
|
||||
print(f"Received message: {message}")
|
||||
print(f"Got response: {response}")
|
||||
|
||||
# Register as async callback
|
||||
register_display_callback('interaction', async_simple_callback, is_async=True)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Use in Your Code">
|
||||
Create and run an agent with callbacks enabled:
|
||||
```python
|
||||
# Create an agent
|
||||
agent = Agent(
|
||||
name="MyAgent",
|
||||
role="Assistant",
|
||||
goal="Help with tasks",
|
||||
backstory="I am a helpful assistant",
|
||||
verbose=True # Enable verbose mode to see callbacks in action
|
||||
)
|
||||
|
||||
# Create a task
|
||||
task = Task(
|
||||
name="simple_task",
|
||||
description="Say hello",
|
||||
agent=agent,
|
||||
expected_output="A greeting"
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task]
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
PraisonAI Agents supports both synchronous and asynchronous callbacks. When registering a callback, specify `is_async=True` for async callbacks. Both sync and async callbacks for the same display type can be executed simultaneously.
|
||||
</Note>
|
||||
|
||||
## Understanding Callbacks
|
||||
|
||||
<Card title="What are Callbacks?" icon="question">
|
||||
Callbacks are functions that get called automatically when specific events occur in your AI agents:
|
||||
- Interactions between user and agent
|
||||
- Error messages
|
||||
- Tool calls
|
||||
- Self-reflection moments
|
||||
- Task completion
|
||||
- Generation progress
|
||||
</Card>
|
||||
|
||||
## Available Callback Types
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Interaction Callback" icon="comments">
|
||||
Triggered when the agent interacts with users
|
||||
</Card>
|
||||
<Card title="Error Callback" icon="triangle-exclamation">
|
||||
Called when errors occur
|
||||
</Card>
|
||||
<Card title="Tool Call Callback" icon="wrench">
|
||||
Activated when tools are used
|
||||
</Card>
|
||||
<Card title="Self Reflection Callback" icon="brain">
|
||||
Triggered during agent self-reflection
|
||||
</Card>
|
||||
<Card title="Instruction Callback" icon="list-check">
|
||||
Called when instructions are processed
|
||||
</Card>
|
||||
<Card title="Generating Callback" icon="spinner">
|
||||
Activated during content generation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Basic Implementation
|
||||
|
||||
### 1. Simple Logging Callback
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
def log_callback(message=None, **kwargs):
|
||||
logging.info(f"Agent message: {message}")
|
||||
|
||||
# Register synchronous callback
|
||||
register_display_callback('interaction', log_callback, is_async=False)
|
||||
|
||||
# Register asynchronous callback
|
||||
async def async_log_callback(message=None, **kwargs):
|
||||
await asyncio.sleep(0)
|
||||
logging.info(f"Agent message: {message}")
|
||||
|
||||
# Register as async callback
|
||||
register_display_callback('interaction', async_log_callback, is_async=True)
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
# Setup logging with file output
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
def detailed_callback(message=None, response=None, **kwargs):
|
||||
logging.info(f"""
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Additional Info: {kwargs}
|
||||
""")
|
||||
|
||||
register_display_callback('interaction', detailed_callback)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Multiple Callback Types
|
||||
|
||||
```python
|
||||
# Error callback
|
||||
def error_callback(message=None):
|
||||
logging.error(f"Error occurred: {message}")
|
||||
|
||||
# Tool call callback
|
||||
def tool_callback(message=None):
|
||||
logging.info(f"Tool called: {message}")
|
||||
|
||||
# Register multiple callbacks
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_callback)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error Handling">
|
||||
Always include error handling in your callbacks:
|
||||
```python
|
||||
def safe_callback(message=None, **kwargs):
|
||||
try:
|
||||
# Process the callback
|
||||
logging.info(message)
|
||||
except Exception as e:
|
||||
logging.error(f"Callback error: {e}")
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Performance">
|
||||
Keep callbacks lightweight:
|
||||
```python
|
||||
# Good - Quick logging
|
||||
def good_callback(message=None):
|
||||
logging.info(message)
|
||||
|
||||
# Bad - Heavy processing
|
||||
def bad_callback(message=None):
|
||||
time.sleep(1) # Delays agent execution
|
||||
process_heavy_task(message)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Complete Example
|
||||
|
||||
Here's a full implementation showing all callback types and proper logging:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, register_display_callback
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Interaction callback
|
||||
def interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
logging.info(f"""
|
||||
=== INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Markdown: {markdown}
|
||||
""")
|
||||
|
||||
# Error callback
|
||||
def error_callback(message=None):
|
||||
logging.error(f"""
|
||||
=== ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
# Tool call callback
|
||||
def tool_call_callback(message=None):
|
||||
logging.info(f"""
|
||||
=== TOOL CALL ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
# Register callbacks
|
||||
register_display_callback('interaction', interaction_callback)
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
|
||||
agent = Agent(
|
||||
name="CallbackAgent",
|
||||
role="Assistant",
|
||||
goal="Demonstrate callbacks",
|
||||
backstory="I am a helpful assistant",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
task = Task(
|
||||
name="callback_task",
|
||||
description="Show how callbacks work",
|
||||
agent=agent,
|
||||
expected_output="Demonstration complete"
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Advanced Examples
|
||||
|
||||
- All callback types
|
||||
- Comprehensive logging
|
||||
- Task callbacks
|
||||
- Tool integration
|
||||
- Multiple agents
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs, register_display_callback
|
||||
from duckduckgo_search import DDGS
|
||||
from rich.console import Console
|
||||
import json
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
filename='ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Callback functions for different display types
|
||||
def interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
"""Callback for display_interaction"""
|
||||
logging.info(f"""
|
||||
=== INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
Markdown: {markdown}
|
||||
""")
|
||||
|
||||
def error_callback(message=None):
|
||||
"""Callback for display_error"""
|
||||
logging.error(f"""
|
||||
=== ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def tool_call_callback(message=None):
|
||||
"""Callback for display_tool_call"""
|
||||
logging.info(f"""
|
||||
=== TOOL CALL ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def instruction_callback(message=None):
|
||||
"""Callback for display_instruction"""
|
||||
logging.info(f"""
|
||||
=== INSTRUCTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def self_reflection_callback(message=None):
|
||||
"""Callback for display_self_reflection"""
|
||||
logging.info(f"""
|
||||
=== SELF REFLECTION ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
def generating_callback(content=None, elapsed_time=None):
|
||||
"""Callback for display_generating"""
|
||||
logging.info(f"""
|
||||
=== GENERATING ===
|
||||
Time: {datetime.now()}
|
||||
Content: {content}
|
||||
Elapsed Time: {elapsed_time}
|
||||
""")
|
||||
|
||||
# Register all callbacks
|
||||
register_display_callback('interaction', interaction_callback)
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
register_display_callback('instruction', instruction_callback)
|
||||
register_display_callback('self_reflection', self_reflection_callback)
|
||||
# register_display_callback('generating', generating_callback)
|
||||
|
||||
def task_callback(output):
|
||||
"""Callback for task completion"""
|
||||
logging.info(f"""
|
||||
=== TASK COMPLETED ===
|
||||
Time: {datetime.now()}
|
||||
Description: {output.description}
|
||||
Agent: {output.agent}
|
||||
Output: {output.raw[:200]}...
|
||||
""")
|
||||
|
||||
def internet_search_tool(query) -> list:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles and URLs.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=10):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during DuckDuckGo search: {e}")
|
||||
return []
|
||||
|
||||
def main():
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
tools=[internet_search_tool],
|
||||
llm="gpt-4o",
|
||||
markdown=True,
|
||||
reflect_llm="gpt-4o",
|
||||
min_reflect=2,
|
||||
max_reflect=4
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
verbose=True,
|
||||
allow_delegation=True,
|
||||
llm="gpt-4o",
|
||||
tools=[],
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Create tasks with callbacks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher,
|
||||
tools=[internet_search_tool],
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.""",
|
||||
expected_output="A blog post of at least 4 paragraphs",
|
||||
agent=writer,
|
||||
context=[task1],
|
||||
callback=task_callback,
|
||||
tools=[]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="json_task",
|
||||
description="""Create a json object with a title of "My Task" and content of "My content".""",
|
||||
expected_output="""JSON output with title and content""",
|
||||
agent=researcher,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="save_output_task",
|
||||
description="""Save the AI blog post to a file""",
|
||||
expected_output="""File saved successfully""",
|
||||
agent=writer,
|
||||
context=[task2],
|
||||
output_file='test.txt',
|
||||
create_directory=True,
|
||||
callback=task_callback
|
||||
)
|
||||
|
||||
# Create and run agents manager
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=True,
|
||||
process="sequential",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
agents.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
## Async Callbacks
|
||||
|
||||
Async callbacks allow you to handle events asynchronously, which is particularly useful for long-running operations or when dealing with multiple agents simultaneously.
|
||||
|
||||
### Basic Async Callback Implementation
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import register_display_callback
|
||||
|
||||
async def async_interaction_callback(message=None, response=None, **kwargs):
|
||||
"""Async callback for handling interactions"""
|
||||
await asyncio.sleep(0) # Non-blocking pause
|
||||
print(f"Async processing - Message: {message}")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Register the async callback
|
||||
register_display_callback('interaction', async_interaction_callback)
|
||||
```
|
||||
|
||||
### Complete Async Example
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, register_display_callback
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
# Setup async logging
|
||||
async def setup_async_logging():
|
||||
logging.basicConfig(
|
||||
filename='async_ai_interactions.log',
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# Async callbacks
|
||||
async def async_interaction_callback(message=None, response=None, markdown=None, generation_time=None):
|
||||
await asyncio.sleep(0)
|
||||
logging.info(f"""
|
||||
=== ASYNC INTERACTION ===
|
||||
Time: {datetime.now()}
|
||||
Generation Time: {generation_time}s
|
||||
Message: {message}
|
||||
Response: {response}
|
||||
""")
|
||||
|
||||
async def async_error_callback(message=None):
|
||||
await asyncio.sleep(0)
|
||||
logging.error(f"""
|
||||
=== ASYNC ERROR ===
|
||||
Time: {datetime.now()}
|
||||
Message: {message}
|
||||
""")
|
||||
|
||||
# Register async callbacks
|
||||
register_display_callback('interaction', async_interaction_callback, is_async=True)
|
||||
register_display_callback('error', async_error_callback, is_async=True)
|
||||
|
||||
# Create async task callback
|
||||
async def async_task_callback(output):
|
||||
await asyncio.sleep(0)
|
||||
logging.info(f"""
|
||||
=== ASYNC TASK COMPLETED ===
|
||||
Time: {datetime.now()}
|
||||
Description: {output.description}
|
||||
Agent: {output.agent}
|
||||
Output: {output.raw[:200]}...
|
||||
""")
|
||||
|
||||
async def main():
|
||||
await setup_async_logging()
|
||||
|
||||
# Create agent with async capabilities
|
||||
agent = Agent(
|
||||
name="AsyncAgent",
|
||||
role="Assistant",
|
||||
goal="Demonstrate async callbacks",
|
||||
backstory="I am an async-capable assistant",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create task with async callback
|
||||
task = Task(
|
||||
name="async_task",
|
||||
description="Demonstrate async callbacks",
|
||||
agent=agent,
|
||||
expected_output="Async demonstration complete",
|
||||
callback=async_task_callback
|
||||
)
|
||||
|
||||
# Create and run agents with async support
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
await agents.start_async()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
### Available Async Functions
|
||||
|
||||
PraisonAI Agents provides several async versions of display functions, prefixed with 'a'. Here's the complete list:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="adisplay_interaction" icon="comments">
|
||||
```python
|
||||
async def adisplay_interaction(
|
||||
message,
|
||||
response,
|
||||
markdown=True,
|
||||
generation_time=None,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version of display_interaction for showing conversations.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_self_reflection" icon="brain">
|
||||
```python
|
||||
async def adisplay_self_reflection(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for displaying agent's self-reflection moments.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_instruction" icon="list-check">
|
||||
```python
|
||||
async def adisplay_instruction(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for showing instructions.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_tool_call" icon="wrench">
|
||||
```python
|
||||
async def adisplay_tool_call(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for displaying tool calls.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_error" icon="triangle-exclamation">
|
||||
```python
|
||||
async def adisplay_error(
|
||||
message: str,
|
||||
console=None
|
||||
)
|
||||
```
|
||||
Async version for error messages.
|
||||
</Card>
|
||||
|
||||
<Card title="adisplay_generating" icon="spinner">
|
||||
```python
|
||||
async def adisplay_generating(
|
||||
content: str = "",
|
||||
start_time: Optional[float] = None
|
||||
)
|
||||
```
|
||||
Async version for showing generation progress.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
#### Example Usage
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import (
|
||||
adisplay_interaction,
|
||||
adisplay_error,
|
||||
adisplay_tool_call
|
||||
)
|
||||
|
||||
async def main():
|
||||
# Display an interaction
|
||||
await adisplay_interaction(
|
||||
message="What's the weather?",
|
||||
response="Let me check that for you.",
|
||||
generation_time=0.5
|
||||
)
|
||||
|
||||
# Display a tool call
|
||||
await adisplay_tool_call(
|
||||
"Calling weather API for location data..."
|
||||
)
|
||||
|
||||
# Handle an error
|
||||
try:
|
||||
raise Exception("API connection failed")
|
||||
except Exception as e:
|
||||
await adisplay_error(str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Best Practices for Async Callbacks
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error Handling">
|
||||
Implement proper error handling in async callbacks:
|
||||
```python
|
||||
async def safe_async_callback(message=None, **kwargs):
|
||||
try:
|
||||
await asyncio.sleep(0)
|
||||
# Process the callback
|
||||
await process_message(message)
|
||||
except Exception as e:
|
||||
logging.error(f"Async callback error: {e}")
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Performance">
|
||||
Optimize async callbacks for better performance:
|
||||
```python
|
||||
async def optimized_async_callback(message=None, **kwargs):
|
||||
# Use asyncio.gather for concurrent operations
|
||||
results = await asyncio.gather(
|
||||
process_message(message),
|
||||
update_status(),
|
||||
log_interaction(message)
|
||||
)
|
||||
return results
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### Key Considerations
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Concurrency" icon="arrows-split-up-and-left">
|
||||
- Use asyncio.gather for parallel operations
|
||||
- Avoid blocking calls in async callbacks
|
||||
- Handle concurrent access to shared resources
|
||||
</Card>
|
||||
<Card title="Resource Management" icon="server">
|
||||
- Implement proper cleanup in async contexts
|
||||
- Use async context managers when appropriate
|
||||
- Monitor memory usage in long-running callbacks
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
When using async callbacks, ensure all dependent operations are also async-compatible to prevent blocking the event loop.
|
||||
</Note>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Callback Not Firing" icon="bug">
|
||||
- Verify callback registration
|
||||
- Check verbose mode is enabled
|
||||
- Ensure correct callback name
|
||||
</Card>
|
||||
<Card title="Logging Issues" icon="file-lines">
|
||||
- Check file permissions
|
||||
- Verify logging configuration
|
||||
- Monitor log file size
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Async Callbacks" icon="bolt" href="./async">
|
||||
Learn about asynchronous callbacks
|
||||
</Card>
|
||||
<Card title="Advanced Patterns" icon="code" href="./advanced">
|
||||
Explore advanced callback patterns
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Remember to handle callbacks efficiently and implement proper error handling to ensure smooth agent operations.
|
||||
</Note>
|
||||
@@ -0,0 +1,287 @@
|
||||
---
|
||||
title: "Code Execution Agent"
|
||||
sidebarTitle: "Code Agent"
|
||||
description: "Learn how to create AI agents that can write and execute Python code safely using e2b code interpreter."
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- e2b_code_interpreter package installed
|
||||
- Basic understanding of Python
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create AI agents that can write and execute Python code in a sandboxed environment!
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Packages">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents e2b_code_interpreter
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Required Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from e2b_code_interpreter import Sandbox
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Code Interpreter">
|
||||
Create a code interpreter function:
|
||||
```python
|
||||
def code_interpreter(code: str):
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Code Agents">
|
||||
Set up your code writing and execution agents:
|
||||
```python
|
||||
code_agent = Agent(
|
||||
name="code_agent",
|
||||
backstory="Expert in writing Python scripts",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
execution_agent = Agent(
|
||||
name="execution_agent",
|
||||
backstory="Expert in executing Python scripts",
|
||||
self_reflect=False,
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Code Agents
|
||||
|
||||
<Card title="What are Code Agents?" icon="question">
|
||||
Code agents are specialized AI agents that can:
|
||||
- Write Python code based on requirements
|
||||
- Execute code safely in a sandboxed environment
|
||||
- Handle code execution results and errors
|
||||
- Work together in a pipeline (writer → executor)
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Code Writer Agent" icon="pencil">
|
||||
Specialized in writing Python code
|
||||
```python
|
||||
Agent(
|
||||
name="code_agent",
|
||||
backstory="Expert in writing Python scripts"
|
||||
)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Code Executor Agent" icon="play">
|
||||
Executes code using sandbox
|
||||
```python
|
||||
Agent(
|
||||
name="execution_agent",
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Sandbox Environment" icon="box">
|
||||
Safe code execution environment using e2b
|
||||
</Card>
|
||||
<Card title="Execution Results" icon="output">
|
||||
Structured output with results and logs
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple Hello World Example
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
# Create agents
|
||||
code_agent = Agent(
|
||||
name="code_agent",
|
||||
backstory="Expert in writing Python scripts",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
execution_agent = Agent(
|
||||
name="execution_agent",
|
||||
backstory="Expert in executing Python scripts",
|
||||
self_reflect=False,
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
code_task = Task(
|
||||
description="Write a simple Python script to print 'Hello, World!'",
|
||||
expected_output="A Python script that prints 'Hello, World!'",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
execution_task = Task(
|
||||
description="Execute the Python script",
|
||||
expected_output="The output of the Python script",
|
||||
agent=execution_agent
|
||||
)
|
||||
|
||||
# Initialize and run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[code_agent, execution_agent],
|
||||
tasks=[code_task, execution_task]
|
||||
)
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
### Advanced Code Generation
|
||||
|
||||
<CodeGroup>
|
||||
```python Data Analysis
|
||||
# Create a data analysis script
|
||||
code_task = Task(
|
||||
description="""
|
||||
Write a Python script that:
|
||||
1. Creates a sample dataset
|
||||
2. Performs basic statistical analysis
|
||||
3. Generates a plot
|
||||
""",
|
||||
agent=code_agent
|
||||
)
|
||||
```
|
||||
|
||||
```python Web Scraping
|
||||
# Create a web scraping script
|
||||
code_task = Task(
|
||||
description="""
|
||||
Write a Python script that:
|
||||
1. Scrapes a website
|
||||
2. Extracts specific data
|
||||
3. Saves to CSV
|
||||
""",
|
||||
agent=code_agent
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Code Safety">
|
||||
Ensure safe code execution:
|
||||
```python
|
||||
# Always use sandbox environment
|
||||
exec_result = Sandbox().run_code(code)
|
||||
|
||||
# Handle errors gracefully
|
||||
if exec_result.error:
|
||||
return {"error": str(exec_result.error)}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Description">
|
||||
Write clear code requirements:
|
||||
```python
|
||||
# Good
|
||||
Task(description="""
|
||||
Write a Python script that:
|
||||
1. Takes user input
|
||||
2. Validates the input
|
||||
3. Processes the data
|
||||
4. Returns formatted output
|
||||
""")
|
||||
|
||||
# Too vague
|
||||
Task(description="Write some Python code")
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Code Generation and Testing
|
||||
```python
|
||||
# Generate code
|
||||
code_task = Task(
|
||||
description="Write a function to calculate fibonacci numbers",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
# Generate test cases
|
||||
test_task = Task(
|
||||
description="Write test cases for the fibonacci function",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
# Execute tests
|
||||
execution_task = Task(
|
||||
description="Run the test cases",
|
||||
agent=execution_agent
|
||||
)
|
||||
```
|
||||
|
||||
### Interactive Code Development
|
||||
```python
|
||||
# Write initial code
|
||||
initial_code_task = Task(
|
||||
description="Write initial version of the script",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
# Test and improve
|
||||
improvement_task = Task(
|
||||
description="Analyze execution results and improve the code",
|
||||
agent=code_agent
|
||||
)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Execution Errors" icon="triangle-exclamation">
|
||||
Check sandbox execution results:
|
||||
```python
|
||||
if exec_result.error:
|
||||
print("[Error]", exec_result.error)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Code Generation" icon="code">
|
||||
Provide clear requirements and constraints in task description
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Advanced Code Generation" icon="graduation-cap" href="./advanced-code">
|
||||
Learn about complex code generation patterns
|
||||
</Card>
|
||||
<Card title="Custom Tools" icon="wrench" href="./custom-tools">
|
||||
Create custom code execution tools
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Code execution agents provide a powerful way to generate and run Python code safely. They're perfect for automated code generation, testing, and execution in a controlled environment.
|
||||
</Note>
|
||||
@@ -0,0 +1,239 @@
|
||||
---
|
||||
title: "Reasoning AI Agents"
|
||||
sidebarTitle: "Reasoning"
|
||||
description: "Reasoning enables AI agents to think logically, solve complex problems autonomously, and make human-like decisions through multi-step logical reasoning."
|
||||
icon: "brain-circuit"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/KNDVWGN3TpM"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
Reasoning in PraisonAI agents enables:
|
||||
- Autonomous problem solving
|
||||
- Multi-step logical reasoning
|
||||
- Human-like decision making
|
||||
- Deep comprehension of tasks
|
||||
- Error handling with alternative solutions
|
||||
|
||||
## Usage
|
||||
|
||||
Reasoning is controlled through reflection cycles using `min_reflect` and `max_reflect` parameters:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="SystemOps",
|
||||
role="System Administrator",
|
||||
goal="Manage and monitor system operations",
|
||||
backstory="You are an expert system administrator",
|
||||
min_reflect=6, # Minimum reflection cycles
|
||||
max_reflect=10 # Maximum reflection cycles
|
||||
)
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Deep Comprehension**: Instead of rule-based responses, agents understand tasks deeply
|
||||
- **Error Recovery**: Agents can reason through errors and find alternative solutions
|
||||
- **Step-by-Step Processing**: Complex tasks are broken down and processed systematically
|
||||
- **Quality Control**: Multiple reflection cycles ensure high-quality outputs
|
||||
- **Adaptive Problem Solving**: Agents can adjust their approach based on reasoning
|
||||
|
||||
## Example
|
||||
|
||||
Here's a complete example showing reasoning in action:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def run_terminal_command(command: str):
|
||||
"""
|
||||
Run a terminal command and return its output.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
print(f"Command output: {result}")
|
||||
return {"stdout": result.stdout, "stderr": result.stderr}
|
||||
except subprocess.CalledProcessError as e:
|
||||
return {"error": str(e), "stdout": e.stdout, "stderr": e.stderr}
|
||||
|
||||
def save_to_file(file_path: str, content: str):
|
||||
"""
|
||||
Save the given content to the specified file path. Create the folder/file if it doesn't exist.
|
||||
"""
|
||||
# Ensure the directory exists
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
# Write the content to the file
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(content)
|
||||
|
||||
return file_path
|
||||
|
||||
# Create System Operations Agent
|
||||
system_ops_agent = Agent(
|
||||
name="SystemOps",
|
||||
role="System Operations Specialist",
|
||||
goal="Execute and manage complex system operations and commands",
|
||||
backstory="""You are an expert system administrator with deep knowledge of Unix/Linux systems.
|
||||
You excel at running complex system commands, managing processes, and handling system operations.
|
||||
You always validate commands before execution and ensure they are safe to run.""",
|
||||
min_reflect=6,
|
||||
max_reflect=10,
|
||||
tools=[run_terminal_command, save_to_file],
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
# Create a complex task that tests various system operations
|
||||
task = Task(
|
||||
name="system_analysis_task",
|
||||
description="""Perform a comprehensive system analysis by executing the following operations in sequence:
|
||||
1. Get system information (OS, kernel version)
|
||||
2. List 5 running processes and sort them by CPU usage
|
||||
3. Check disk space usage and list directories over 1GB
|
||||
4. Display current system load and memory usage
|
||||
5. List 5 network connections
|
||||
6. Create a summary report with all findings in a text file called system_report.txt
|
||||
|
||||
Do it step by step. One task at a time.
|
||||
Save only the Summary report in the file.
|
||||
Use appropriate commands for each step and ensure proper error handling.""",
|
||||
expected_output="A comprehensive system report containing all requested information saved in system_report.txt",
|
||||
agent=system_ops_agent,
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[system_ops_agent],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
## e2b Tool Integration Example
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs
|
||||
import json
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
def code_interpret(code: str):
|
||||
"""
|
||||
A function to demonstrate running Python code dynamically using e2b_code_interpreter.
|
||||
"""
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
|
||||
# 1) Create Agents
|
||||
web_scraper_agent = Agent(
|
||||
name="WebScraper",
|
||||
role="Web Scraper",
|
||||
goal="Extract URLs from https://quotes.toscrape.com/",
|
||||
backstory="An expert in data extraction from websites, adept at navigating and retrieving detailed information.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
url_data_extractor_agent = Agent(
|
||||
name="URLDataExtractor",
|
||||
role="URL Data Extractor",
|
||||
goal="Crawl each URL for data extraction",
|
||||
backstory="Specializes in crawling websites to gather comprehensive data, ensuring nothing is missed from each link.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
blog_writer_agent = Agent(
|
||||
name="BlogWriter",
|
||||
role="Creative Content Writer",
|
||||
goal="Create engaging and insightful blog posts from provided data",
|
||||
backstory="An experienced content creator and storyteller with a knack for weaving compelling narratives. Skilled at analyzing quotes and creating meaningful connections that resonate with readers.",
|
||||
tools=[code_interpret],
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# 2) Create Tasks
|
||||
task_url_extraction = Task(
|
||||
name="url_extraction_task",
|
||||
description="""Use code_interpret to run Python code that fetches https://quotes.toscrape.com/
|
||||
and extracts 5 URLs from the page, then outputs them as a list. Only first 5 urls""",
|
||||
expected_output="A list of URLs extracted from the source page.",
|
||||
agent=web_scraper_agent,
|
||||
output_file="urls.txt"
|
||||
)
|
||||
|
||||
task_data_extraction = Task(
|
||||
name="data_extraction_task",
|
||||
description="""Take the URLs from url_extraction_task, crawl each URL and extract all pertinent
|
||||
data using code_interpret to run Python code, then output raw txt, not the html.""",
|
||||
expected_output="Raw data collected from each crawled URL.",
|
||||
agent=url_data_extractor_agent,
|
||||
context=[task_url_extraction]
|
||||
)
|
||||
|
||||
blog_writing_task = Task(
|
||||
name="blog_writing_task",
|
||||
description="""Write an engaging blog post using the extracted quotes data. The blog post should:
|
||||
1. Have a catchy title
|
||||
2. Include relevant quotes from the data
|
||||
3. Provide commentary and insights about the quotes
|
||||
4. Be well-structured with introduction, body, and conclusion
|
||||
5. Be approximately 500 words long""",
|
||||
expected_output="A well-written blog post incorporating the extracted quotes with analysis",
|
||||
agent=blog_writer_agent,
|
||||
context=[task_data_extraction],
|
||||
output_file="blog_post.txt"
|
||||
)
|
||||
|
||||
# 3) Create and run Agents manager
|
||||
agents_manager = PraisonAIAgents(
|
||||
agents=[web_scraper_agent, url_data_extractor_agent, blog_writer_agent],
|
||||
tasks=[task_url_extraction, task_data_extraction, blog_writing_task],
|
||||
verbose=True,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents_manager.start()
|
||||
```
|
||||
|
||||
## Integration with Tools
|
||||
|
||||
Reasoning works particularly well with tools that require complex decision-making:
|
||||
|
||||
- **Code Interpreter**: For dynamic code generation and execution
|
||||
- **System Operations**: For multi-step system management tasks
|
||||
- **Data Analysis**: For complex data processing workflows
|
||||
- **Web Scraping**: For intelligent data extraction and processing
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Higher reflection cycles mean more thorough reasoning but longer processing time
|
||||
- `min_reflect` ensures minimum quality standards
|
||||
- `max_reflect` prevents excessive processing
|
||||
- Balance based on task complexity and quality requirements
|
||||
@@ -0,0 +1,102 @@
|
||||
---
|
||||
title: "Self Reflection AI Agents"
|
||||
sidebarTitle: "Self-Reflection"
|
||||
description: "Self-reflection is a powerful feature in PraisonAI that enables agents to evaluate and improve their own responses before delivering them. This leads to higher quality outputs and more reliable task completion."
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/vLXobEN2Vc8"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
When an agent with self-reflection enabled processes a task:
|
||||
1. It generates an initial response using its tools and capabilities
|
||||
2. The agent then reflects on its own response, evaluating:
|
||||
- Completeness
|
||||
- Accuracy
|
||||
- Relevance
|
||||
- Quality
|
||||
3. Based on this reflection, the agent may revise and improve its response
|
||||
4. This cycle can repeat until the agent is satisfied with the quality
|
||||
|
||||
## Usage
|
||||
|
||||
Self-reflection is enabled by default for all agents. You can explicitly control it using the `self_reflect` parameter:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at analyzing tech trends",
|
||||
self_reflect=True # Enable self-reflection (default)
|
||||
)
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Higher Quality Outputs**: Agents can catch and correct potential issues before delivering responses
|
||||
- **More Reliable Task Completion**: Self-reflection helps ensure all aspects of a task are properly addressed
|
||||
- **Conscious Decision Making**: Agents evaluate their own work, leading to more thoughtful responses
|
||||
- **Improved Accuracy**: Multiple reflection cycles help refine and perfect the output
|
||||
|
||||
## Integration with Processes
|
||||
|
||||
Self-reflection works seamlessly with both sequential and hierarchical processes:
|
||||
|
||||
- **Sequential**: Each agent self-reflects on their individual tasks
|
||||
- **Hierarchical**: Agents self-reflect before reporting to the manager agent, ensuring high-quality inputs for decision-making
|
||||
|
||||
## Example
|
||||
|
||||
Here's a complete example showing self-reflection in action:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at analyzing tech trends",
|
||||
self_reflect=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report on AI trends",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
In this example, the researcher agent will:
|
||||
1. Research AI advancements
|
||||
2. Generate an initial report
|
||||
3. Self-reflect on the report's quality
|
||||
4. Make improvements if needed
|
||||
5. Deliver the final, refined output
|
||||
|
||||
## Performance Impact
|
||||
|
||||
While self-reflection adds additional processing time, the improvement in output quality often justifies the extra computation.
|
||||
The number of reflection cycles need to be manually optimized to balance quality and performance.
|
||||
@@ -0,0 +1,322 @@
|
||||
---
|
||||
title: "Structured AI Agents"
|
||||
description: "Learn how to create AI agents that return structured, type-safe outputs using Pydantic models and JSON."
|
||||
icon: "cube"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of Python and Pydantic
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create AI agents that return structured, validated outputs in just a few lines of code!
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Required Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Tools
|
||||
from pydantic import BaseModel
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Your Data Model">
|
||||
Create a Pydantic model to define your output structure:
|
||||
```python
|
||||
class AnalysisReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Structured Tasks">
|
||||
Create tasks with structured outputs:
|
||||
```python
|
||||
research_task = Task(
|
||||
description="Research recent AI developments",
|
||||
agent=researcher,
|
||||
expected_output="Research findings"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze research findings",
|
||||
agent=analyst,
|
||||
output_pydantic=AnalysisReport, # For Pydantic output
|
||||
# or output_json=AnalysisReport # For JSON output
|
||||
expected_output="Structured analysis report"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Structured Outputs
|
||||
|
||||
<Card title="What are Structured Outputs?" icon="question">
|
||||
Structured outputs allow you to:
|
||||
- Define exact shape of data using Pydantic models
|
||||
- Get type-safe, validated responses
|
||||
- Choose between Pydantic objects or JSON
|
||||
- Ensure consistent output format across agent responses
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Pydantic Models" icon="cube">
|
||||
Define your data structure
|
||||
```python
|
||||
class ResearchReport(BaseModel):
|
||||
title: str
|
||||
content: str
|
||||
```
|
||||
</Card>
|
||||
<Card title="Task Configuration" icon="gear">
|
||||
Configure output format
|
||||
```python
|
||||
Task(output_pydantic=Model)
|
||||
# or
|
||||
Task(output_json=Model)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Output Validation" icon="check">
|
||||
Automatic validation of responses against your model
|
||||
</Card>
|
||||
<Card title="Format Options" icon="code">
|
||||
Choose between Pydantic objects or JSON output
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Output Types
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Pydantic Output" icon="cube">
|
||||
```python
|
||||
task = Task(
|
||||
output_pydantic=AnalysisReport
|
||||
)
|
||||
# Returns Pydantic object
|
||||
```
|
||||
Get type-safe Pydantic model instances
|
||||
</Card>
|
||||
<Card title="JSON Output" icon="brackets-curly">
|
||||
```python
|
||||
task = Task(
|
||||
output_json=AnalysisReport
|
||||
)
|
||||
# Returns JSON dict
|
||||
```
|
||||
Get JSON dictionary matching model schema
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Research Analysis with Structured Output
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Tools
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Define output structure
|
||||
class AnalysisReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="AIResearcher",
|
||||
role="Technology Research Analyst",
|
||||
tools=[Tools.internet_search]
|
||||
)
|
||||
|
||||
analyst = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Insights Specialist"
|
||||
)
|
||||
|
||||
# Define structured tasks
|
||||
research_task = Task(
|
||||
name="gather_research",
|
||||
description="Research recent AI developments in 2024",
|
||||
agent=researcher,
|
||||
expected_output="Research findings"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
name="analyze_findings",
|
||||
description="Analyze research findings and create structured report",
|
||||
agent=analyst,
|
||||
output_pydantic=AnalysisReport,
|
||||
expected_output="Structured analysis report"
|
||||
)
|
||||
|
||||
# Initialize and run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, analyst],
|
||||
tasks=[research_task, analysis_task]
|
||||
)
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
### Different Output Formats
|
||||
|
||||
<CodeGroup>
|
||||
```python Pydantic
|
||||
# Get Pydantic model instance
|
||||
analysis_task = Task(
|
||||
description="Analyze findings",
|
||||
agent=analyst,
|
||||
output_pydantic=AnalysisReport
|
||||
)
|
||||
|
||||
# Result will be AnalysisReport instance
|
||||
result.pydantic.title
|
||||
result.pydantic.findings
|
||||
result.pydantic.summary
|
||||
```
|
||||
|
||||
```python JSON
|
||||
# Get JSON dictionary
|
||||
analysis_task = Task(
|
||||
description="Analyze findings",
|
||||
agent=analyst,
|
||||
output_json=AnalysisReport
|
||||
)
|
||||
|
||||
# Result will be dictionary
|
||||
result.json_dict['title']
|
||||
result.json_dict['findings']
|
||||
result.json_dict['summary']
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Model Design">
|
||||
Design clear, focused Pydantic models:
|
||||
```python
|
||||
# Good
|
||||
class ResearchReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
|
||||
# Too complex
|
||||
class Report(BaseModel):
|
||||
title: str
|
||||
subtitle: Optional[str]
|
||||
findings: List[Dict[str, Any]]
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Output Format Selection">
|
||||
Choose the right output format:
|
||||
```python
|
||||
# Use Pydantic when you need:
|
||||
# - Type validation
|
||||
# - Model methods
|
||||
task = Task(output_pydantic=Model)
|
||||
|
||||
# Use JSON when you need:
|
||||
# - Simple dictionary access
|
||||
# - Serialization
|
||||
task = Task(output_json=Model)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Research and Structured Analysis
|
||||
```python
|
||||
class ResearchReport(BaseModel):
|
||||
topic: str
|
||||
findings: str
|
||||
sources: list[str]
|
||||
|
||||
class Analysis(BaseModel):
|
||||
key_points: list[str]
|
||||
implications: str
|
||||
recommendations: str
|
||||
|
||||
research_task = Task(
|
||||
description="Research quantum computing",
|
||||
agent=researcher,
|
||||
output_pydantic=ResearchReport
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze research implications",
|
||||
agent=analyst,
|
||||
output_pydantic=Analysis
|
||||
)
|
||||
```
|
||||
|
||||
### Data Collection and Summary
|
||||
```python
|
||||
class DataPoint(BaseModel):
|
||||
timestamp: str
|
||||
value: float
|
||||
source: str
|
||||
|
||||
class Summary(BaseModel):
|
||||
average: float
|
||||
trends: str
|
||||
insights: str
|
||||
|
||||
collection_task = Task(
|
||||
description="Collect data points",
|
||||
output_pydantic=DataPoint
|
||||
)
|
||||
|
||||
summary_task = Task(
|
||||
description="Summarize data",
|
||||
output_pydantic=Summary
|
||||
)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Validation Errors" icon="triangle-exclamation">
|
||||
Check if your model matches the expected output structure
|
||||
```python
|
||||
# Print model schema
|
||||
print(Model.schema_json())
|
||||
```
|
||||
</Card>
|
||||
<Card title="Output Format" icon="code">
|
||||
Verify you're accessing the right output field:
|
||||
- `result.pydantic` for Pydantic
|
||||
- `result.json_dict` for JSON
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Advanced Models" icon="graduation-cap" href="./advanced-models">
|
||||
Learn about advanced Pydantic model configurations
|
||||
</Card>
|
||||
<Card title="Custom Validation" icon="check-double" href="./validation">
|
||||
Add custom validation to your models
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Structured outputs make your AI agents more reliable and their responses more predictable. They're perfect for production systems where data consistency is crucial.
|
||||
</Note>
|
||||
@@ -4,6 +4,16 @@ description: "Guide for creating and using multimodal AI agents in PraisonAI for
|
||||
icon: "images"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/hjAWmUT1qqY"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
# Multimodal AI Agents
|
||||
|
||||
PraisonAI supports multimodal AI agents capable of processing various types of media including images and videos. This enables you to create agents that can understand and analyze visual content alongside text.
|
||||
|
||||
@@ -1,132 +1,327 @@
|
||||
---
|
||||
title: "Praison AI"
|
||||
description: "Home page for PraisonAI documentation, featuring installation options, user interfaces, and quick start guides for multi-agent LLM systems"
|
||||
icon: "home"
|
||||
sidebarTitle: "Home"
|
||||
description: "Comprehensive guide to PraisonAI - an AI Agents Framework with Self Reflection, combining PraisonAI Agents, AutoGen, and CrewAI for building multi-agent LLM systems"
|
||||
icon: "house"
|
||||
openGraph:
|
||||
url: "/"
|
||||
seo:
|
||||
canonical: "/"
|
||||
---
|
||||
|
||||
# Home
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Fn1lQjC0GO0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="/logo/dark.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="/logo/light.png" />
|
||||
<img alt="PraisonAI Logo" src="/logo/light.png" style={{display: "block", margin: "auto"}} />
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/MervinPraison/PraisonAI"><img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" /></a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI"><img src="https://img.shields.io/github/v/release/MervinPraison/PraisonAI" alt="Latest Stable Version" /></a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License" /></a>
|
||||
</p>
|
||||
|
||||
# Praison AI
|
||||
|
||||
Praison AI, leveraging both AutoGen and CrewAI or any other agent framework, represents a low-code, centralised framework designed to simplify the creation and orchestration of multi-agent systems for various LLM applications, emphasizing ease of use, customization, and human-agent interaction.
|
||||
|
||||
<div align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="images/architecture-dark.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="images/architecture-light.png" />
|
||||
<img alt="PraisonAI Architecture" src="images/architecture-light.png" />
|
||||
</picture>
|
||||
<Note>
|
||||
Welcome to PraisonAI - Your comprehensive solution for building and managing multi-agent LLM systems with self-reflection capabilities.
|
||||
</Note>
|
||||
<div className="flex justify-start w-full max-w-xs sm:max-w-sm md:max-w-md">
|
||||
<img
|
||||
src="images/praisonai-logo-black.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto rounded-lg shadow-md block dark:hidden"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
<img
|
||||
src="images/praisonai-logo-light.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto rounded-lg shadow-md hidden dark:block"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-4 my-8">
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/v/release/MervinPraison/PraisonAI" alt="Latest Stable Version" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/stars/MervinPraison/PraisonAI?style=social" alt="GitHub Stars" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/forks/MervinPraison/PraisonAI?style=social" alt="GitHub Forks" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Different User Interfaces:
|
||||
<Tip>
|
||||
PraisonAI combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration.
|
||||
</Tip>
|
||||
|
||||
| Interface | Description | URL |
|
||||
|---|---|---|
|
||||
| **UI** | Multi Agents such as CrewAI or AutoGen | [https://docs.praison.ai/ui/ui](https://docs.praison.ai/ui/ui) |
|
||||
| **Chat** | Chat with 100+ LLMs, single AI Agent | [https://docs.praison.ai/ui/chat](https://docs.praison.ai/ui/chat) |
|
||||
| **Code** | Chat with entire Codebase, single AI Agent | [https://docs.praison.ai/ui/code](https://docs.praison.ai/ui/code) |
|
||||
## Key Features
|
||||
|
||||
## Google Colab Multi Agents
|
||||
|
||||
| | Cookbook | Open in Colab |
|
||||
| ------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Basic | PraisonAI | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
|
||||
| Include Tools | PraisonAI Tools | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
|
||||
<CardGroup cols={2}>
|
||||
<Card title="AI Agents Creation" icon="robot">
|
||||
Automated creation and management of AI agents with self-reflection capabilities
|
||||
</Card>
|
||||
<Card title="Framework Integration" icon="puzzle-piece">
|
||||
Seamless integration with CrewAI and AutoGen frameworks
|
||||
</Card>
|
||||
<Card title="LLM Support" icon="brain">
|
||||
Support for 100+ Language Learning Models
|
||||
</Card>
|
||||
<Card title="Code Integration" icon="code">
|
||||
Chat with your entire codebase using advanced context understanding
|
||||
</Card>
|
||||
<Card title="Interactive UI" icon="desktop">
|
||||
Rich, interactive user interfaces for better control and monitoring
|
||||
</Card>
|
||||
<Card title="Configuration" icon="gear">
|
||||
YAML-based configuration for easy setup and customization
|
||||
</Card>
|
||||
<Card title="Tool Integration" icon="screwdriver-wrench">
|
||||
Custom tool integration for extended functionality
|
||||
</Card>
|
||||
<Card title="Search Capability" icon="magnifying-glass">
|
||||
Internet search using Crawl4AI and Tavily
|
||||
</Card>
|
||||
</CardGroup>
|
||||
<br />
|
||||
<div className="relative w-full aspect-video overflow-hidden rounded-lg shadow-lg mb-8">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full border-0"
|
||||
src="https://www.youtube.com/embed/Fn1lQjC0GO0"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
style={{
|
||||
maxWidth: '100vw',
|
||||
margin: '0 auto'
|
||||
}}
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Installation Options
|
||||
|
||||
### Basic Installation
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
<Tabs>
|
||||
<Tab title="No Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Auto Mode">
|
||||
```bash
|
||||
praisonai --auto create a movie script about Robots in Mars
|
||||
```
|
||||
|
||||
### Framework-specific Installation
|
||||
```bash
|
||||
# Install with CrewAI support
|
||||
pip install "praisonai[crewai]"
|
||||
This will automatically create required agents and complete the task
|
||||
|
||||
# Install with AutoGen support
|
||||
pip install "praisonai[autogen]"
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.py` file
|
||||
|
||||
# Install with both frameworks
|
||||
pip install "praisonai[crewai,autogen]"
|
||||
```
|
||||
## Code Example
|
||||
|
||||
### UI and Additional Features
|
||||
```bash
|
||||
pip install "praisonai[ui]" # UI support
|
||||
pip install "praisonai[chat]" # Chat interface
|
||||
pip install "praisonai[code]" # Code interface
|
||||
pip install "praisonai[realtime]" # Realtime voice interaction
|
||||
pip install "praisonai[call]" # Call feature
|
||||
```
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
## TL;DR Multi Agents
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
```bash
|
||||
pip install praisonai
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
praisonai --init create a movie script about dog in moon
|
||||
praisonai
|
||||
```
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
## Initialise
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
```
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
Generate your OPENAI API KEY from here: https://platform.openai.com/api-keys
|
||||
```python Advanced
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
Note: You can use other providers such as Ollama, Mistral ... etc. Details are provided at the bottom.
|
||||
# Create multiple agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="You are a content strategist",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Define multiple tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="Create a blog post about AI advancements",
|
||||
expected_output="A blog post",
|
||||
agent=writer
|
||||
)
|
||||
|
||||
# Run with hierarchical process
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
verbose=False,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Integration Options
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ollama Integration">
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Groq Integration">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Logging Configuration">
|
||||
```bash
|
||||
# Basic logging
|
||||
export LOGLEVEL=info
|
||||
|
||||
```bash
|
||||
praisonai --init create a movie script about dog in moon
|
||||
```
|
||||
This will automatically create agents.yaml file in the current directory.
|
||||
# Advanced logging
|
||||
export LOGLEVEL=debug
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### To initialse with a specific agent framework (Optional):
|
||||
## Use Cases
|
||||
|
||||
```bash
|
||||
praisonai --framework autogen --init create movie script about cat in mars
|
||||
```
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Customer Service" icon="headset">
|
||||
Build intelligent support agents that can handle customer inquiries and resolve issues autonomously.
|
||||
</Card>
|
||||
<Card title="Data Analysis" icon="chart-line">
|
||||
Create agents that can process, analyze, and derive insights from complex datasets.
|
||||
</Card>
|
||||
<Card title="Content Creation" icon="pen-nib">
|
||||
Deploy agents that can generate, edit, and optimize content across various formats.
|
||||
</Card>
|
||||
<Card title="Process Automation" icon="gears">
|
||||
Automate complex workflows with intelligent agents that can coordinate and execute tasks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Run
|
||||
## Praison AI Package Overall Features
|
||||
|
||||
```bash
|
||||
praisonai
|
||||
```
|
||||
<Frame caption="PraisonAI Features Overview">
|
||||
<div className="w-full max-w-4xl mx-auto">
|
||||
<img
|
||||
src="images/architecture-light.png"
|
||||
alt="PraisonAI Features"
|
||||
className="w-full h-auto rounded-lg shadow-lg block dark:hidden"
|
||||
width="1200"
|
||||
height="800"
|
||||
/>
|
||||
<img
|
||||
src="images/architecture-dark.png"
|
||||
alt="PraisonAI Features"
|
||||
className="w-full h-auto rounded-lg shadow-lg hidden dark:block"
|
||||
width="1200"
|
||||
height="800"
|
||||
/>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
python -m praisonai
|
||||
```
|
||||
## Features
|
||||
|
||||
### Specify the agent framework (Optional):
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Self-Reflection" icon="brain-circuit" href="/features/selfreflection">
|
||||
Agents that evaluate and improve their own responses for higher accuracy
|
||||
</Card>
|
||||
<Card title="Reasoning" icon="gears" href="/features/reasoning">
|
||||
Multi-step logical reasoning and autonomous problem solving
|
||||
</Card>
|
||||
<Card title="CrewAI Framework" icon="users-gear" href="/framework/crewai">
|
||||
Build collaborative AI teams with CrewAI integration
|
||||
</Card>
|
||||
<Card title="AutoGen Framework" icon="robot" href="/framework/autogen">
|
||||
Create autonomous agent networks using AutoGen
|
||||
</Card>
|
||||
<Card title="Multimodal Agents" icon="icons" href="/framework/multimodalagents">
|
||||
Work with agents that can process text, images, and other data types
|
||||
</Card>
|
||||
<Card title="Train" icon="graduation-cap" href="/train">
|
||||
Train and fine-tune your LLMs for specific tasks and domains. Then use it as an AI Agent.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
```bash
|
||||
praisonai --framework autogen
|
||||
```
|
||||
## User Interfaces
|
||||
|
||||
### Full Automatic Mode
|
||||
|
||||
```bash
|
||||
praisonai --auto create a movie script about Dog in Moon
|
||||
```
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Multi Agents UI" icon="users" href="/ui/ui">
|
||||
Work with CrewAI or AutoGen multi-agent systems
|
||||
</Card>
|
||||
<Card title="Chat Interface" icon="comments" href="/ui/chat">
|
||||
Chat with 100+ LLMs using a single AI Agent
|
||||
</Card>
|
||||
<Card title="Code Interface" icon="code" href="/ui/code">
|
||||
Interact with your entire codebase
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -8,8 +8,66 @@ openGraph:
|
||||
seo:
|
||||
canonical: "/"
|
||||
---
|
||||
<div className="flex justify-start w-full max-w-xs sm:max-w-sm md:max-w-md">
|
||||
<img
|
||||
src="images/praisonai-logo-black.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto rounded-lg shadow-md block dark:hidden"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
<img
|
||||
src="images/praisonai-logo-light.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto rounded-lg shadow-md hidden dark:block"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem' }}>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/stars/MervinPraison/PraisonAI?style=social" alt="GitHub Stars" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/forks/MervinPraison/PraisonAI?style=social" alt="GitHub Forks" />
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://trendshift.io/repositories/9130" target="_blank">
|
||||
<img src="https://trendshift.io/api/badge/repositories/9130" alt="MervinPraison/PraisonAI | Trendshift" />
|
||||
</a>
|
||||
## Key Features
|
||||
|
||||
<div className="relative w-full aspect-video overflow-hidden">
|
||||
<CardGroup cols={2}>
|
||||
<Card title="AI Agents Creation" icon="robot">
|
||||
Automated creation and management of AI agents with self-reflection capabilities
|
||||
</Card>
|
||||
<Card title="Framework Integration" icon="puzzle-piece">
|
||||
Seamless integration with CrewAI and AutoGen frameworks
|
||||
</Card>
|
||||
<Card title="LLM Support" icon="brain">
|
||||
Support for 100+ Language Learning Models
|
||||
</Card>
|
||||
<Card title="Code Integration" icon="code">
|
||||
Chat with your entire codebase using advanced context understanding
|
||||
</Card>
|
||||
<Card title="Interactive UI" icon="desktop">
|
||||
Rich, interactive user interfaces for better control and monitoring
|
||||
</Card>
|
||||
<Card title="Configuration" icon="gear">
|
||||
YAML-based configuration for easy setup and customization
|
||||
</Card>
|
||||
<Card title="Tool Integration" icon="screwdriver-wrench">
|
||||
Custom tool integration for extended functionality
|
||||
</Card>
|
||||
<Card title="Search Capability" icon="magnifying-glass">
|
||||
Internet search using Crawl4AI and Tavily
|
||||
</Card>
|
||||
</CardGroup>
|
||||
<br />
|
||||
<div className="relative w-full aspect-video overflow-hidden rounded-lg shadow-lg mb-8">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full border-0"
|
||||
src="https://www.youtube.com/embed/Fn1lQjC0GO0"
|
||||
@@ -23,228 +81,261 @@ seo:
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-start w-full max-w-xs sm:max-w-sm md:max-w-md">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="images/praisonai-logo-black.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="images/praisonai-logo-light.png" />
|
||||
## Installation Options
|
||||
|
||||
<Tabs>
|
||||
<Tab title="No Code">
|
||||
<Tip>
|
||||
PraisonAI combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration.
|
||||
</Tip>
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Auto Mode">
|
||||
```bash
|
||||
praisonai --auto create a movie script about Robots in Mars
|
||||
```
|
||||
|
||||
This will automatically create required agents and complete the task
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.py` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create an agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o"
|
||||
)
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Create multiple agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI",
|
||||
backstory="You are an expert at a technology research group",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="You are a content strategist",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# Define multiple tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="Create a blog post about AI advancements",
|
||||
expected_output="A blog post",
|
||||
agent=writer
|
||||
)
|
||||
|
||||
# Run with hierarchical process
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
verbose=False,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Integration Options
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ollama Integration">
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Groq Integration">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Logging Configuration">
|
||||
```bash
|
||||
# Basic logging
|
||||
export LOGLEVEL=info
|
||||
|
||||
# Advanced logging
|
||||
export LOGLEVEL=debug
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Use Cases
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Customer Service" icon="headset">
|
||||
Build intelligent support agents that can handle customer inquiries and resolve issues autonomously.
|
||||
</Card>
|
||||
<Card title="Data Analysis" icon="chart-line">
|
||||
Create agents that can process, analyze, and derive insights from complex datasets.
|
||||
</Card>
|
||||
<Card title="Content Creation" icon="pen-nib">
|
||||
Deploy agents that can generate, edit, and optimize content across various formats.
|
||||
</Card>
|
||||
<Card title="Process Automation" icon="gears">
|
||||
Automate complex workflows with intelligent agents that can coordinate and execute tasks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Praison AI Package Overall Features
|
||||
|
||||
<Frame caption="PraisonAI Features Overview">
|
||||
<div className="w-full max-w-4xl mx-auto">
|
||||
<img
|
||||
src="images/praisonai-logo-light.png"
|
||||
alt="PraisonAI Logo"
|
||||
className="w-full h-auto"
|
||||
width="400"
|
||||
height="100"
|
||||
/>
|
||||
</picture>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-4 my-4">
|
||||
<a href="https://github.com/MervinPraison/PraisonAI">
|
||||
<img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" />
|
||||
</a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI">
|
||||
<img src="https://img.shields.io/github/v/release/MervinPraison/PraisonAI" alt="Latest Stable Version" />
|
||||
</a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI">
|
||||
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI">
|
||||
<img src="https://img.shields.io/github/stars/MervinPraison/PraisonAI?style=social" alt="GitHub Stars" />
|
||||
</a>
|
||||
<a href="https://github.com/MervinPraison/PraisonAI">
|
||||
<img src="https://img.shields.io/github/forks/MervinPraison/PraisonAI?style=social" alt="GitHub Forks" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
## Key Features
|
||||
|
||||
- 🤖 Automated AI Agents Creation
|
||||
- 🔄 Use CrewAI or AutoGen Framework
|
||||
- 💯 100+ LLM Support
|
||||
- 💻 Chat with ENTIRE Codebase
|
||||
- 🖥️ Interactive UIs
|
||||
- 📄 YAML-based Configuration
|
||||
- 🛠️ Custom Tool Integration
|
||||
- 🔍 Internet Search Capability (using Crawl4AI and Tavily)
|
||||
- 👁️ Vision Language Model (VLM) Support
|
||||
- 🎙️ Real-time Voice Interaction
|
||||
|
||||
## Using No Code
|
||||
|
||||
### Auto Mode:
|
||||
```bash
|
||||
pip install praisonai
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
praisonai --auto create a movie script about Robots in Mars
|
||||
```
|
||||
|
||||
### Initialise Mode:
|
||||
```bash
|
||||
pip install praisonai
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
praisonai --init create a movie script about Robots in Mars
|
||||
praisonai
|
||||
```
|
||||
|
||||
## Using Coding
|
||||
|
||||
Light weight package dedicated for coding:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
Create app.py file and add the code below:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# 1. Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Senior Research Analyst",
|
||||
goal="Uncover cutting-edge developments in AI and data science",
|
||||
backstory="""You are an expert at a technology research group,
|
||||
skilled in identifying trends and analyzing complex data.""",
|
||||
verbose=True,
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Tech Content Strategist",
|
||||
goal="Craft compelling content on tech advancements",
|
||||
backstory="""You are a content strategist known for
|
||||
making complex tech topics interesting and easy to understand.""",
|
||||
llm="gpt-4o",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
# 2. Define Tasks
|
||||
task1 = Task(
|
||||
name="research_task",
|
||||
description="""Analyze 2024's AI advancements.
|
||||
Find major trends, new technologies, and their effects.""",
|
||||
expected_output="""A detailed report on 2024 AI advancements""",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="writing_task",
|
||||
description="""Create a blog post about major AI advancements using the insights you have.
|
||||
Make it interesting, clear, and suited for tech enthusiasts.
|
||||
It should be at least 4 paragraphs long.""",
|
||||
expected_output="A blog post of at least 4 paragraphs",
|
||||
agent=writer,
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
verbose=False,
|
||||
process="hierarchical",
|
||||
manager_llm="gpt-4o"
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
Run:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
## Ollama Integration
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
```
|
||||
|
||||
## Groq Integration
|
||||
Replace xxxx with Groq API KEY:
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
|
||||
## Logging
|
||||
```bash
|
||||
export LOGLEVEL=info
|
||||
```
|
||||
|
||||
Advanced logging:
|
||||
```bash
|
||||
export LOGLEVEL=debug
|
||||
```
|
||||
|
||||
<div className="w-full max-w-4xl mx-auto">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="images/architecture-light.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="images/architecture-dark.png" />
|
||||
<img
|
||||
src="images/architecture-dark.png"
|
||||
alt="PraisonAI Architecture"
|
||||
className="w-full h-auto"
|
||||
src="images/architecture-light.png"
|
||||
alt="PraisonAI Features"
|
||||
className="w-full h-auto rounded-lg shadow-lg block dark:hidden"
|
||||
width="1200"
|
||||
height="800"
|
||||
/>
|
||||
</picture>
|
||||
</div>
|
||||
<img
|
||||
src="images/architecture-dark.png"
|
||||
alt="PraisonAI Features"
|
||||
className="w-full h-auto rounded-lg shadow-lg hidden dark:block"
|
||||
width="1200"
|
||||
height="800"
|
||||
/>
|
||||
</div>
|
||||
</Frame>
|
||||
|
||||
## Features
|
||||
|
||||
## Different User Interfaces:
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Self-Reflection" icon="brain-circuit" href="/features/selfreflection">
|
||||
Agents that evaluate and improve their own responses for higher accuracy
|
||||
</Card>
|
||||
<Card title="Reasoning" icon="gears" href="/features/reasoning">
|
||||
Multi-step logical reasoning and autonomous problem solving
|
||||
</Card>
|
||||
<Card title="CrewAI Framework" icon="users-gear" href="/framework/crewai">
|
||||
Build collaborative AI teams with CrewAI integration
|
||||
</Card>
|
||||
<Card title="AutoGen Framework" icon="robot" href="/framework/autogen">
|
||||
Create autonomous agent networks using AutoGen
|
||||
</Card>
|
||||
<Card title="Multimodal Agents" icon="icons" href="/framework/multimodalagents">
|
||||
Work with agents that can process text, images, and other data types
|
||||
</Card>
|
||||
<Card title="Train" icon="graduation-cap" href="/train">
|
||||
Train and fine-tune your LLMs for specific tasks and domains. Then use it as an AI Agent.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| Interface | Description | URL |
|
||||
|---|---|---|
|
||||
| **UI** | Multi Agents such as CrewAI or AutoGen | [https://docs.praison.ai/ui/ui](https://docs.praison.ai/ui/ui) |
|
||||
| **Chat** | Chat with 100+ LLMs, single AI Agent | [https://docs.praison.ai/ui/chat](https://docs.praison.ai/ui/chat) |
|
||||
| **Code** | Chat with entire Codebase, single AI Agent | [https://docs.praison.ai/ui/code](https://docs.praison.ai/ui/code) |
|
||||
## User Interfaces
|
||||
|
||||
## Google Colab Multi Agents
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Multi Agents UI" icon="users" href="/ui/ui">
|
||||
Work with CrewAI or AutoGen multi-agent systems
|
||||
</Card>
|
||||
<Card title="Chat Interface" icon="comments" href="/ui/chat">
|
||||
Chat with 100+ LLMs using a single AI Agent
|
||||
</Card>
|
||||
<Card title="Code Interface" icon="code" href="/ui/code">
|
||||
Interact with your entire codebase
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| | Cookbook | Open in Colab |
|
||||
| ------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Basic | PraisonAI | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
|
||||
| Include Tools | PraisonAI Tools | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
|
||||
<Note>
|
||||
Welcome to PraisonAI - Your comprehensive solution for building and managing multi-agent LLM systems with self-reflection capabilities.
|
||||
</Note>
|
||||
|
||||
## Install
|
||||
|
||||
| PraisonAI | PraisonAI Code | PraisonAI Chat |
|
||||
| --- | --- | --- |
|
||||
| `pip install praisonai` | `pip install "praisonai[code]"` | `pip install "praisonai[chat]"` |
|
||||
|
||||
## TL;DR Multi Agents
|
||||
|
||||
```bash
|
||||
pip install praisonai
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
praisonai --init create a movie script about dog in moon
|
||||
praisonai
|
||||
```
|
||||
|
||||
## Prerequisite:
|
||||
### Export API KEY
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
|
||||
## Automatically Create Agents to Perform a Task
|
||||
|
||||
```bash
|
||||
praisonai --init create a movie script about dog in moon
|
||||
```
|
||||
## Run
|
||||
```bash
|
||||
praisonai
|
||||
```
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem' }}>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://static.pepy.tech/badge/PraisonAI" alt="Total Downloads" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/v/release/MervinPraison/PraisonAI" alt="Latest Stable Version" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/stars/MervinPraison/PraisonAI?style=social" alt="GitHub Stars" />
|
||||
</div>
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/forks/MervinPraison/PraisonAI?style=social" alt="GitHub Forks" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,24 +4,73 @@ description: 'Get started with PraisonAI, an intelligent AI-powered tool'
|
||||
icon: "hand-wave"
|
||||
---
|
||||
|
||||
Welcome to PraisonAI documentation! PraisonAI is a low-code, centralized framework designed to simplify the creation and orchestration of multi-agent systems for various LLM applications, emphasizing ease of use, customization, and human-agent interaction.
|
||||
<Note>
|
||||
PraisonAI is a low-code, centralized framework designed to simplify the creation and orchestration of multi-agent systems for various LLM applications.
|
||||
</Note>
|
||||
|
||||
## Key Features
|
||||
# Welcome to PraisonAI
|
||||
|
||||
- Leverages both AutoGen and CrewAI
|
||||
- Simplifies multi-agent system creation
|
||||
- Emphasizes ease of use and customization
|
||||
- Supports human-agent interaction
|
||||
<Frame caption="PraisonAI Framework Overview">
|
||||

|
||||
</Frame>
|
||||
|
||||
## Core Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Multi-Agent Systems" icon="users">
|
||||
Create and orchestrate sophisticated multi-agent systems with ease
|
||||
</Card>
|
||||
<Card title="Framework Integration" icon="puzzle-piece">
|
||||
Seamlessly integrates AutoGen and CrewAI capabilities
|
||||
</Card>
|
||||
<Card title="Low-Code Design" icon="code">
|
||||
Build complex AI systems with minimal coding required
|
||||
</Card>
|
||||
<Card title="Human-AI Interaction" icon="people-arrows">
|
||||
Enhanced support for human-agent collaboration
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started with PraisonAI, check out our [Installation](./installation) guide.
|
||||
<Steps>
|
||||
<Step title="Installation">
|
||||
Follow our [Installation Guide](./installation) to set up PraisonAI
|
||||
</Step>
|
||||
<Step title="Quick Overview">
|
||||
Check out our [TL;DR](./tldr) for a rapid introduction
|
||||
</Step>
|
||||
<Step title="First Project">
|
||||
Create your first project following our [Quick Start](./quickstart) guide
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
For a quick overview, see our [TL;DR](./tldr) page.
|
||||
## Key Components
|
||||
|
||||
| Component | Description | Benefits |
|
||||
|:----------|:------------|:---------|
|
||||
| **UI Tools** | Intuitive interface components | Easy system interaction and monitoring |
|
||||
| **Model Integration** | Support for various LLM models | Flexibility in AI model selection |
|
||||
| **Tool System** | Extensible tool framework | Custom capability integration |
|
||||
| **API Layer** | Comprehensive API access | Full programmatic control |
|
||||
|
||||
## Explore Further
|
||||
|
||||
- [User Interface](./ui/ui)
|
||||
- [Models](./models)
|
||||
- [Tools](./tools)
|
||||
- [API Reference](./api-reference)
|
||||
<CardGroup cols={2}>
|
||||
<Card title="User Interface" icon="desktop" href="./ui/ui">
|
||||
Learn about our intuitive UI components
|
||||
</Card>
|
||||
<Card title="Models" icon="robot" href="./models">
|
||||
Explore supported AI models
|
||||
</Card>
|
||||
<Card title="Tools" icon="wrench" href="./tools">
|
||||
Discover available tools and integrations
|
||||
</Card>
|
||||
<Card title="API Reference" icon="code" href="./api-reference">
|
||||
Access comprehensive API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Start with our no-code interface to learn the basics, then transition to code-based development for more advanced use cases.
|
||||
</Tip>
|
||||
@@ -60,7 +60,24 @@
|
||||
"pages": ["index"]
|
||||
},
|
||||
{
|
||||
"group": "Getting Started",
|
||||
"group": "Getting Started (Code)",
|
||||
"pages": [
|
||||
"code/introduction",
|
||||
"code/installation",
|
||||
"code/quickstart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Core Concepts",
|
||||
"pages": [
|
||||
"concepts/agents",
|
||||
"concepts/tasks",
|
||||
"concepts/process",
|
||||
"concepts/tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Getting Started (No Code)",
|
||||
"pages": [
|
||||
"introduction",
|
||||
"tldr",
|
||||
@@ -80,11 +97,18 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Core Concepts",
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/selfreflection",
|
||||
"features/reasoning",
|
||||
"framework/multimodalagents",
|
||||
"features/async",
|
||||
"features/mini",
|
||||
"features/codeagent",
|
||||
"features/structured",
|
||||
"features/callbacks",
|
||||
"train",
|
||||
"framework/praisonaiagents",
|
||||
"framework/multimodalagents",
|
||||
"framework/crewai",
|
||||
"framework/autogen"
|
||||
]
|
||||
@@ -94,18 +118,18 @@
|
||||
"pages": [
|
||||
"models",
|
||||
"models/openai",
|
||||
"models/ollama",
|
||||
"models/groq",
|
||||
"models/google",
|
||||
"models/openrouter",
|
||||
"models/anthropic",
|
||||
"models/cohere",
|
||||
"models/mistral",
|
||||
"models/openrouter",
|
||||
"models/ollama",
|
||||
"models/other"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Tools",
|
||||
"group": "Tools (No Code)",
|
||||
"pages": [
|
||||
"tools",
|
||||
"tools/custom",
|
||||
@@ -144,7 +168,8 @@
|
||||
"api/praisonaiagents/index",
|
||||
"api/praisonaiagents/agent/agent",
|
||||
"api/praisonaiagents/agents/agents",
|
||||
"api/praisonaiagents/task/task"
|
||||
"api/praisonaiagents/task/task",
|
||||
"api/praisonaiagents/process/process"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,6 +4,47 @@ description: "Overview of supported language models in PraisonAI, including Open
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
## Supported Models for Code
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ollama Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Groq Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Google Gemini" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Jan AI Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:1337/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="LM Studio Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:1234/v1
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="OpenRouter Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://openrouter.ai/api/v1
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
||||
## Supported Models for No Code
|
||||
|
||||
| PraisonAI Chat | PraisonAI Code | PraisonAI (Multi-Agents) |
|
||||
| --- | --- | --- |
|
||||
| [Litellm](https://litellm.vercel.app/docs/providers) | [Litellm](https://litellm.vercel.app/docs/providers) | Below Models |
|
||||
|
||||
@@ -6,6 +6,8 @@ icon: "robot"
|
||||
|
||||
# Add Anthropic to Praison AI
|
||||
|
||||
## No Code
|
||||
|
||||
```bash
|
||||
pip install langchain-anthropic
|
||||
```
|
||||
|
||||
@@ -6,6 +6,8 @@ icon: "brain"
|
||||
|
||||
# Add COHERE to Praison AI
|
||||
|
||||
## No Code
|
||||
|
||||
```bash
|
||||
pip install langchain-cohere
|
||||
```
|
||||
|
||||
@@ -6,6 +6,18 @@ icon: "google"
|
||||
|
||||
# Add Google Gemini to Praison AI
|
||||
|
||||
## Code
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Google Gemini" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
## No Code
|
||||
|
||||
```bash
|
||||
pip install langchain-google-genai
|
||||
```
|
||||
|
||||
@@ -6,6 +6,19 @@ icon: "bolt"
|
||||
|
||||
# Add GROQ to Praison AI
|
||||
|
||||
## Code
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Groq Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxx
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## No Code
|
||||
|
||||
```bash
|
||||
export GROQ_API_KEY=xxxxxxxxxx
|
||||
```
|
||||
|
||||
@@ -6,6 +6,8 @@ icon: "wind"
|
||||
|
||||
# Add Mistral to Praison AI
|
||||
|
||||
## No Code
|
||||
|
||||
Note: If you want to use Mistral via Ollama, please refer to Ollama document. This is for using Mistral from https://mistral.ai
|
||||
|
||||
## Using Single Agent
|
||||
|
||||
@@ -6,6 +6,18 @@ icon: "terminal"
|
||||
|
||||
# Add Ollama to Praison AI
|
||||
|
||||
## Code
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ollama Integration" defaultOpen>
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## No Code
|
||||
|
||||
### agents.yaml file
|
||||
|
||||
```yaml
|
||||
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M840.5 798.2L662.3 599.5l-151 173.7-173.7-173.7-167.7 201c-21 30.4 0.9 71.8 37.9 71.6l594.7-3.3c36.2-0.1 57.8-40.3 38-70.6z" fill="#FFB89A" /><path d="M741.6 647.3l-52.3-47.7c-12.2-11.2-31.2-10.3-42.4 1.9s-10.3 31.2 1.9 42.4l52.3 47.7c5.8 5.3 13 7.8 20.2 7.8 8.1 0 16.2-3.3 22.2-9.8 11.2-12.1 10.3-31.1-1.9-42.3zM631.2 546.5c-12.4-11-31.4-9.8-42.3 2.6l-98.8 111.7-171-165.7L87.9 724.7c-11.8 11.7-11.8 30.7-0.1 42.4 5.9 5.9 13.6 8.9 21.3 8.9 7.6 0 15.3-2.9 21.1-8.7l189.4-188.1 173.8 168.5L633.8 589c11-12.5 9.8-31.5-2.6-42.5z" fill="#33CC99" /><path d="M721.3 342.8m-35.1 0a35.1 35.1 0 1 0 70.2 0 35.1 35.1 0 1 0-70.2 0Z" fill="#33CC99" /><path d="M743.2 175.1H191.6c-70.6 0-128.3 57.7-128.3 128.3v499.2c0 70.6 57.7 128.3 128.3 128.3h551.5c70.6 0 128.3-57.7 128.3-128.3V303.5c0.1-70.6-57.7-128.4-128.2-128.4z m68.3 627.6c0 18.1-7.1 35.2-20.1 48.2-13 13-30.1 20.1-48.2 20.1H191.6c-18.1 0-35.2-7.1-48.2-20.1-13-13-20.1-30.1-20.1-48.2V303.5c0-18.1 7.1-35.2 20.1-48.2 13-13 30.1-20.1 48.2-20.1h551.5c18.1 0 35.2 7.1 48.2 20.1 13 13 20.1 30.1 20.1 48.2v499.2z" fill="#45484C" /><path d="M799.7 90.9H237.2c-16.6 0-30 13.4-30 30s13.4 30 30 30h562.4c26.1 0 50.8 10.3 69.4 28.9 18.6 18.6 28.9 43.3 28.9 69.4v482.4c0 16.6 13.4 30 30 30s30-13.4 30-30V249.2C958 161.9 887 90.9 799.7 90.9z" fill="#45484C" /></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 429 B |
|
After Width: | Height: | Size: 872 B |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M570.2 842c-50.6 0-278.7-180-278.7-401.9 0-58.8-2.9-133.1-1-183.9-50.8 3.2-91.4 45.7-91.4 97.3v272.1c37.4 194.7 137.5 334 255.2 334 69.5 0 132.9-48.6 180.9-128.5-20.8 7.1-42.6 10.9-65 10.9z" fill="#FFB89A" /><path d="M926.1 191.8C900.5 74.1 817.9 62.1 704.9 62.1c-29.1 0-60.3 0.8-93 0.8-36 0-70.5-1.1-102.5-1.1-109.7 0-189.8 12.5-201.3 123.7-20.4 198.3 30 617.1 306.1 617.1S939 414.3 926.1 191.8z m-76.9 268.5c-9.5 47.9-22.3 90.8-38.1 127.7-16.8 39.2-37 71.4-60 95.8-37.3 39.5-82.1 58.7-137 58.7-53.4 0-97.6-20.1-134.9-61.6-45.5-50.5-79.8-131.5-99-234.2-15.6-83.5-20.3-178.9-12.4-255.2 1.8-17.3 5.7-30.7 11.6-39.8 4.4-6.8 10.1-11.7 18.7-15.8 25.8-12.5 70.8-14.2 111.4-14.2 15 0 30.7 0.2 47.3 0.5 17.8 0.3 36.2 0.6 55.2 0.6 17.2 0 33.9-0.2 50-0.4 15.1-0.2 29.3-0.4 43.1-0.4 44.5 0 89.5 1.8 118 15.1 15.9 7.4 33.4 20.8 43.6 63 2.6 53.3 3.6 153.5-17.5 260.2z" fill="#4E5155" /><path d="M532 841.7c-32.5 22.3-70.6 33.7-113.2 33.7-29.7 0-57.3-6-82.1-17.7-23.2-11-44.7-27.4-63.9-48.7-46-50.9-80.3-131.3-99.2-232.4-15.1-80.6-19.6-172.9-12-246.8 3-29.5 12-50.2 27.5-63.2 14.2-12 35.1-19.2 65.8-22.9 16.5-2 28.2-16.9 26.3-33.3-2-16.5-16.9-28.2-33.3-26.3-42.9 5.1-73.8 16.7-97.4 36.5-27.9 23.5-43.8 57.2-48.5 103-8.2 79.3-3.4 178.1 12.7 264 9.7 51.9 23.4 99.4 40.6 141.2 19.8 48.1 44.4 88.6 73 120.4 51.6 57.2 115.7 86.2 190.6 86.2 55 0 104.5-14.9 147.2-44.2 13.7-9.4 17.1-28.1 7.7-41.7-9.4-13.7-28.1-17.2-41.8-7.8z" fill="#4E5155" /><path d="M519.7 248.5c-16.6 0-30 13.4-30 30v91.3c0 16.6 13.4 30 30 30s30-13.4 30-30v-91.3c0-16.6-13.5-30-30-30zM299.5 385.5c0-16.6-13.4-30-30-30s-30 13.4-30 30v91.3c0 16.6 13.4 30 30 30s30-13.4 30-30v-91.3zM754.6 248.5c-16.6 0-30 13.4-30 30v91.3c0 16.6 13.4 30 30 30s30-13.4 30-30v-91.3c0-16.6-13.4-30-30-30zM716.7 554.5c0-16.6-13.4-30-30-30H551v30c0 58.5 38.1 123.7 92.8 123.7 22.9 0 45-11.9 62.2-33.6 10.3-13 8.1-31.9-4.9-42.1-13-10.3-31.9-8.1-42.1 4.9-5.3 6.7-11.1 10.9-15.1 10.9-4.3 0-11.9-5.1-19.1-16.4-3.3-5.3-6.2-11.2-8.4-17.4h70.4c16.4 0 29.9-13.4 29.9-30zM401.6 704c-25.4 0-46.1-24.2-46.1-53.9 0-16.6-13.4-30-30-30s-30 13.4-30 30c0 62.8 47.6 113.9 106.1 113.9 16.6 0 30-13.4 30-30s-13.5-30-30-30z" fill="#33CC99" /></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M861.9 383.8H218.1c-36.4 0-66.1-29.8-66.1-66.1V288c0-36.4 29.8-66.1 66.1-66.1h643.8c36.4 0 66.1 29.8 66.1 66.1v29.7c0 36.3-29.8 66.1-66.1 66.1z" fill="#FFB89A" /><path d="M822.9 129.2H199.8c-77.2 0-140.4 63.2-140.4 140.4v487.2c0 77.2 63.2 140.4 140.4 140.4h623.1c77.2 0 140.4-63.2 140.4-140.4V269.6c0-77.2-63.2-140.4-140.4-140.4z m80.4 177H760.4L864.6 201c5.4 3.3 10.4 7.3 15 11.8 15.3 15.3 23.7 35.4 23.7 56.8v36.6z m-673.3 0l104-117h61.3l-109.1 117H230z m247.4-117h169.2L532 306.2H368.3l109.1-117z m248.8 0h65.6L676 306.2h-60l112.5-114.8-2.3-2.2zM143 212.9c15.3-15.3 35.4-23.7 56.8-23.7h53.9l-104 117h-30.4v-36.5c0.1-21.4 8.5-41.5 23.7-56.8z m736.6 600.7c-15.3 15.3-35.4 23.7-56.8 23.7h-623c-21.3 0-41.5-8.4-56.8-23.7-15.3-15.3-23.7-35.4-23.7-56.8V366.2h783.9v390.6c0.1 21.3-8.3 41.5-23.6 56.8z" fill="#45484C" /><path d="M400.5 770.6V430.9L534.1 508c14.3 8.3 19.3 26.6 11 41-8.3 14.3-26.6 19.3-41 11l-43.6-25.2v131.8l114.1-65.9-7.5-4.3c-14.3-8.3-19.3-26.6-11-41 8.3-14.3 26.6-19.3 41-11l97.5 56.3-294.1 169.9z" fill="#33CC99" /></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 168 KiB |
|
After Width: | Height: | Size: 167 KiB |
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M188.3 766.5a94.4 135.8 0 1 0 188.8 0 94.4 135.8 0 1 0-188.8 0Z" fill="#FFB89A" /><path d="M931.5 397s0-0.1 0 0c-34.2-82.6-119.3-141-218.8-141-129.7 0-234.9 99.3-234.9 221.9 0 52.1 19.1 100.1 50.9 138 1 14.5 1.8 29.1 1.8 43.6 0 148.5 98.1 269 219.2 269 121 0 219.2-120.4 219.2-269 0-70.1-1.7-214.7-37.4-262.5z m-36.6 347.5c-8.7 25.3-21.1 47.9-36.8 67.1-29.8 36.5-68.3 56.7-108.5 56.7s-78.7-20.1-108.5-56.7c-15.7-19.2-28-41.8-36.8-67.1-9.3-26.9-13.9-55.5-13.9-85.1 0-16.8-1-33.5-2-47.7l-1.3-19.5-12.6-15c-24.1-28.6-36.8-63-36.8-99.3 0-89.3 78.5-161.9 174.9-161.9 36.4 0 71.4 10.3 101 29.7 28.4 18.7 65.5 81.7 65.5 81.7s17.9 27.5 24.7 98.2c4.5 46.5 5 95.9 5 133.8 0.1 29.6-4.6 58.2-13.9 85.1zM377.1 219.9c-51.8 0-93.8 42-93.8 93.8s42 93.8 93.8 93.8 93.8-42 93.8-93.8-42-93.8-93.8-93.8z m0 127.5c-18.6 0-33.8-15.2-33.8-33.8 0-18.6 15.2-33.8 33.8-33.8 18.6 0 33.8 15.2 33.8 33.8 0 18.7-15.1 33.8-33.8 33.8z" fill="#45484C" /><path d="M521.2 206.7m-50.3 0a50.3 50.3 0 1 0 100.6 0 50.3 50.3 0 1 0-100.6 0Z" fill="#45484C" /><path d="M653 156.4m-50.3 0a50.3 50.3 0 1 0 100.6 0 50.3 50.3 0 1 0-100.6 0Z" fill="#45484C" /><path d="M781.9 158.4m-50.3 0a50.3 50.3 0 1 0 100.6 0 50.3 50.3 0 1 0-100.6 0Z" fill="#45484C" /><path d="M909 206.7m-50.3 0a50.3 50.3 0 1 0 100.6 0 50.3 50.3 0 1 0-100.6 0Z" fill="#45484C" /><path d="M263.9 602.7c44.7 0 81 31.5 81 70.3 0 20.9-10.2 35.9-18.7 44.8l-15.9 19.7-0.5 27.2c0.7 7.2 0.6 16.9 0.6 24.7v4.8c0 33.7-27.4 61.2-61.2 61.2-14.9 0-33.3-9.6-48.1-25-15.2-15.9-24.6-35.9-24.6-52.3v-3.2c0-12.7 0-36.2 1-60.2 1.4-33 7.4-57.3 7.4-57.3 3.9-14.7 13.4-28.2 26.8-38 14.8-11 32.8-16.7 52.2-16.7m0-60c-66.4 0-122 42.4-137 99.4-10.9 23-10.4 112.6-10.4 135.9 0 66.9 65.8 137.3 132.7 137.3 66.9 0 121.2-54.3 121.2-121.2 0-9.2 0.3-23-0.8-34.9 22-23 35.4-53.2 35.4-86.3-0.1-71.9-63.2-130.2-141.1-130.2zM444.4 559.9c-26.4 0-47.8 21.4-47.8 47.8s21.4 47.8 47.8 47.8 47.8-21.4 47.8-47.8-21.4-47.8-47.8-47.8zM377.1 494.5c-15.2 0-27.5 12.3-27.5 27.5s12.3 27.5 27.5 27.5 27.5-12.3 27.5-27.5c0-15.3-12.3-27.5-27.5-27.5zM288.1 471.5c-15.2 0-27.5 12.3-27.5 27.5s12.3 27.5 27.5 27.5 27.5-12.3 27.5-27.5-12.4-27.5-27.5-27.5zM188.3 477.9c-15.2 0-27.5 12.3-27.5 27.5s12.3 27.5 27.5 27.5 27.5-12.3 27.5-27.5-12.3-27.5-27.5-27.5zM100.6 538.4c-15.2 0-27.5 12.3-27.5 27.5s12.3 27.5 27.5 27.5 27.5-12.3 27.5-27.5c-0.1-15.2-12.4-27.5-27.5-27.5z" fill="#45484C" /><path d="M670.1 584.6c-41.4 0-80.2-20.3-103.9-54.3-9.5-13.6-6.2-32.3 7.4-41.8 13.6-9.5 32.3-6.2 41.8 7.4 12.5 17.9 33 28.6 54.7 28.6 36.8 0 66.7-29.9 66.7-66.7 0-19.8-8.7-38.4-23.9-51.2-12.7-10.6-14.4-29.6-3.7-42.3s29.6-14.4 42.3-3.7c28.9 24.2 45.4 59.6 45.4 97.2-0.1 70-56.9 126.8-126.8 126.8z" fill="#33CC99" /><path d="M853 556.4c-26 0-49.6-14.5-60.1-36.9-7-15-0.6-32.9 14.4-39.9s32.9-0.6 39.9 14.4c0.3 0.6 2.2 2.4 5.8 2.4 1.2 0 2.3-0.2 3.3-0.6 15.5-5.9 32.8 1.8 38.7 17.3 5.9 15.5-1.8 32.8-17.3 38.7-7.9 3.1-16.2 4.6-24.7 4.6z" fill="#33CC99" /></svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: "PraisonAI Chat"
|
||||
description: "Guide to PraisonAI's chat interface with support for 100+ LLMs, internet search, vision models, and custom database configurations"
|
||||
icon: "comments"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: "PraisonAI Code"
|
||||
description: "Guide to PraisonAI's code interface for interacting with your codebase using AI, including file management, model configuration, and advanced features"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "PraisonAI User Interface (UI)"
|
||||
title: "UI"
|
||||
description: "Comprehensive guide to PraisonAI's user interfaces, including Chainlit, Gradio, and Streamlit integrations with step-by-step setup instructions"
|
||||
icon: "desktop"
|
||||
---
|
||||
|
||||
@@ -244,13 +244,13 @@ vertex = ["google-auth (>=2,<3)"]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.7.0"
|
||||
version = "4.8.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352"},
|
||||
{file = "anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48"},
|
||||
{file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"},
|
||||
{file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -261,7 +261,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
|
||||
|
||||
[package.extras]
|
||||
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
|
||||
trio = ["trio (>=0.26.1)"]
|
||||
|
||||
[[package]]
|
||||
@@ -480,6 +480,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tinycss2 = {version = ">=1.1.0,<1.5", optional = true, markers = "extra == \"css\""}
|
||||
webencodings = "*"
|
||||
|
||||
[package.extras]
|
||||
@@ -1091,13 +1092,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "cohere"
|
||||
version = "5.13.4"
|
||||
version = "5.13.5"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
files = [
|
||||
{file = "cohere-5.13.4-py3-none-any.whl", hash = "sha256:f3d81cef93ded8ea57dde6d4a547598846c9e836c18834fe0c6d2bb3da1d8e8f"},
|
||||
{file = "cohere-5.13.4.tar.gz", hash = "sha256:ade5e817368a73dbdaa2bf5a812ad0952d59bdf3e583928e5207774b964d7d6b"},
|
||||
{file = "cohere-5.13.5-py3-none-any.whl", hash = "sha256:cce9754003239f7a1c862ed6ebb54aad7996da2c1225688e8af9b91b0845cab5"},
|
||||
{file = "cohere-5.13.5.tar.gz", hash = "sha256:036ffe2da54a2928412d5895c79f0bf11c91c51f6f562cb2b8fb85ed48c68ed7"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1483,19 +1484,19 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "duckduckgo-search"
|
||||
version = "7.1.1"
|
||||
version = "7.2.0"
|
||||
description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine."
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "duckduckgo_search-7.1.1-py3-none-any.whl", hash = "sha256:753b2237fd8a9a4cbf06c788aaf0cfc7e00f4623e8f854d0525682ff31770093"},
|
||||
{file = "duckduckgo_search-7.1.1.tar.gz", hash = "sha256:1874e55aa6eac3de2d0e9b556b70f35ed0cd7a4544d7417cf38216275b3de009"},
|
||||
{file = "duckduckgo_search-7.2.0-py3-none-any.whl", hash = "sha256:511abfa5e3e98592ae6a155d819b981adaac9e66c1ee2bb2eb0d7086e29316e2"},
|
||||
{file = "duckduckgo_search-7.2.0.tar.gz", hash = "sha256:2163d4b78388ab70731094fdc86f4474d9fb9027c975e5aa2f0638e596a7e7b8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=8.1.7"
|
||||
lxml = ">=5.3.0"
|
||||
primp = ">=0.9.2"
|
||||
primp = ">=0.9.3"
|
||||
|
||||
[package.extras]
|
||||
dev = ["mypy (>=1.13.0)", "pytest (>=8.3.4)", "pytest-dependency (>=0.6.0)", "ruff (>=0.8.3)"]
|
||||
@@ -2086,13 +2087,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.156.0"
|
||||
version = "2.157.0"
|
||||
description = "Google API Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "google_api_python_client-2.156.0-py2.py3-none-any.whl", hash = "sha256:6352185c505e1f311f11b0b96c1b636dcb0fec82cd04b80ac5a671ac4dcab339"},
|
||||
{file = "google_api_python_client-2.156.0.tar.gz", hash = "sha256:b809c111ded61716a9c1c7936e6899053f13bae3defcdfda904bd2ca68065b9c"},
|
||||
{file = "google_api_python_client-2.157.0-py2.py3-none-any.whl", hash = "sha256:0b0231db106324c659bf8b85f390391c00da57a60ebc4271e33def7aac198c75"},
|
||||
{file = "google_api_python_client-2.157.0.tar.gz", hash = "sha256:2ee342d0967ad1cedec43ccd7699671d94bff151e1f06833ea81303f9a6d86fd"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2539,13 +2540,13 @@ colorama = ">=0.4"
|
||||
|
||||
[[package]]
|
||||
name = "grpc-google-iam-v1"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
description = "IAM API client library"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "grpc-google-iam-v1-0.13.1.tar.gz", hash = "sha256:3ff4b2fd9d990965e410965253c0da6f66205d5a8291c4c31c6ebecca18a9001"},
|
||||
{file = "grpc_google_iam_v1-0.13.1-py2.py3-none-any.whl", hash = "sha256:c3e86151a981811f30d5e7330f271cee53e73bb87755e88cc3b6f0c7b5fe374e"},
|
||||
{file = "grpc_google_iam_v1-0.14.0-py2.py3-none-any.whl", hash = "sha256:fb4a084b30099ba3ab07d61d620a0d4429570b13ff53bd37bac75235f98b7da4"},
|
||||
{file = "grpc_google_iam_v1-0.14.0.tar.gz", hash = "sha256:c66e07aa642e39bb37950f9e7f491f70dad150ac9801263b42b2814307c2df99"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2555,70 +2556,70 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4
|
||||
|
||||
[[package]]
|
||||
name = "grpcio"
|
||||
version = "1.68.1"
|
||||
version = "1.69.0"
|
||||
description = "HTTP/2-based RPC framework"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "grpcio-1.68.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:d35740e3f45f60f3c37b1e6f2f4702c23867b9ce21c6410254c9c682237da68d"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d99abcd61760ebb34bdff37e5a3ba333c5cc09feda8c1ad42547bea0416ada78"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f8261fa2a5f679abeb2a0a93ad056d765cdca1c47745eda3f2d87f874ff4b8c9"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0feb02205a27caca128627bd1df4ee7212db051019a9afa76f4bb6a1a80ca95e"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:919d7f18f63bcad3a0f81146188e90274fde800a94e35d42ffe9eadf6a9a6330"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:963cc8d7d79b12c56008aabd8b457f400952dbea8997dd185f155e2f228db079"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ccf2ebd2de2d6661e2520dae293298a3803a98ebfc099275f113ce1f6c2a80f1"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-win32.whl", hash = "sha256:2cc1fd04af8399971bcd4f43bd98c22d01029ea2e56e69c34daf2bf8470e47f5"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2e743e51cb964b4975de572aa8fb95b633f496f9fcb5e257893df3be854746"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:55857c71641064f01ff0541a1776bfe04a59db5558e82897d35a7793e525774c"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4b177f5547f1b995826ef529d2eef89cca2f830dd8b2c99ffd5fde4da734ba73"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3522c77d7e6606d6665ec8d50e867f13f946a4e00c7df46768f1c85089eae515"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d1fae6bbf0816415b81db1e82fb3bf56f7857273c84dcbe68cbe046e58e1ccd"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298ee7f80e26f9483f0b6f94cc0a046caf54400a11b644713bb5b3d8eb387600"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb5780e2e740b6b4f2d208e90453591036ff80c02cc605fea1af8e6fc6b1bbe"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ddda1aa22495d8acd9dfbafff2866438d12faec4d024ebc2e656784d96328ad0"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-win32.whl", hash = "sha256:b33bd114fa5a83f03ec6b7b262ef9f5cac549d4126f1dc702078767b10c46ed9"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f20ebec257af55694d8f993e162ddf0d36bd82d4e57f74b31c67b3c6d63d8b2"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:8829924fffb25386995a31998ccbbeaa7367223e647e0122043dfc485a87c666"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3aed6544e4d523cd6b3119b0916cef3d15ef2da51e088211e4d1eb91a6c7f4f1"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:4efac5481c696d5cb124ff1c119a78bddbfdd13fc499e3bc0ca81e95fc573684"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ab2d912ca39c51f46baf2a0d92aa265aa96b2443266fc50d234fa88bf877d8e"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c87ce2a97434dffe7327a4071839ab8e8bffd0054cc74cbe971fba98aedd60"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e4842e4872ae4ae0f5497bf60a0498fa778c192cc7a9e87877abd2814aca9475"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:255b1635b0ed81e9f91da4fcc8d43b7ea5520090b9a9ad9340d147066d1d3613"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-win32.whl", hash = "sha256:7dfc914cc31c906297b30463dde0b9be48e36939575eaf2a0a22a8096e69afe5"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0c8ddabef9c8f41617f213e527254c41e8b96ea9d387c632af878d05db9229c"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:a47faedc9ea2e7a3b6569795c040aae5895a19dde0c728a48d3c5d7995fda385"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:390eee4225a661c5cd133c09f5da1ee3c84498dc265fd292a6912b65c421c78c"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:66a24f3d45c33550703f0abb8b656515b0ab777970fa275693a2f6dc8e35f1c1"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c08079b4934b0bf0a8847f42c197b1d12cba6495a3d43febd7e99ecd1cdc8d54"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8720c25cd9ac25dd04ee02b69256d0ce35bf8a0f29e20577427355272230965a"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:04cfd68bf4f38f5bb959ee2361a7546916bd9a50f78617a346b3aeb2b42e2161"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c28848761a6520c5c6071d2904a18d339a796ebe6b800adc8b3f474c5ce3c3ad"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-win32.whl", hash = "sha256:77d65165fc35cff6e954e7fd4229e05ec76102d4406d4576528d3a3635fc6172"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-win_amd64.whl", hash = "sha256:a8040f85dcb9830d8bbb033ae66d272614cec6faceee88d37a88a9bd1a7a704e"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:eeb38ff04ab6e5756a2aef6ad8d94e89bb4a51ef96e20f45c44ba190fa0bcaad"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a3869a6661ec8f81d93f4597da50336718bde9eb13267a699ac7e0a1d6d0bea"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:2c4cec6177bf325eb6faa6bd834d2ff6aa8bb3b29012cceb4937b86f8b74323c"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12941d533f3cd45d46f202e3667be8ebf6bcb3573629c7ec12c3e211d99cfccf"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80af6f1e69c5e68a2be529990684abdd31ed6622e988bf18850075c81bb1ad6e"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e8dbe3e00771bfe3d04feed8210fc6617006d06d9a2679b74605b9fed3e8362c"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:83bbf5807dc3ee94ce1de2dfe8a356e1d74101e4b9d7aa8c720cc4818a34aded"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-win32.whl", hash = "sha256:8cb620037a2fd9eeee97b4531880e439ebfcd6d7d78f2e7dcc3726428ab5ef63"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-win_amd64.whl", hash = "sha256:52fbf85aa71263380d330f4fce9f013c0798242e31ede05fcee7fbe40ccfc20d"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb400138e73969eb5e0535d1d06cae6a6f7a15f2cc74add320e2130b8179211a"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a1b988b40f2fd9de5c820f3a701a43339d8dcf2cb2f1ca137e2c02671cc83ac1"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:96f473cdacfdd506008a5d7579c9f6a7ff245a9ade92c3c0265eb76cc591914f"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:37ea3be171f3cf3e7b7e412a98b77685eba9d4fd67421f4a34686a63a65d99f9"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ceb56c4285754e33bb3c2fa777d055e96e6932351a3082ce3559be47f8024f0"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dffd29a2961f3263a16d73945b57cd44a8fd0b235740cb14056f0612329b345e"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:025f790c056815b3bf53da850dd70ebb849fd755a4b1ac822cb65cd631e37d43"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-win32.whl", hash = "sha256:1098f03dedc3b9810810568060dea4ac0822b4062f537b0f53aa015269be0a76"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-win_amd64.whl", hash = "sha256:334ab917792904245a028f10e803fcd5b6f36a7b2173a820c0b5b076555825e1"},
|
||||
{file = "grpcio-1.68.1.tar.gz", hash = "sha256:44a8502dd5de653ae6a73e2de50a401d84184f0331d0ac3daeb044e66d5c5054"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:2060ca95a8db295ae828d0fc1c7f38fb26ccd5edf9aa51a0f44251f5da332e97"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2e52e107261fd8fa8fa457fe44bfadb904ae869d87c1280bf60f93ecd3e79278"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:316463c0832d5fcdb5e35ff2826d9aa3f26758d29cdfb59a368c1d6c39615a11"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26c9a9c4ac917efab4704b18eed9082ed3b6ad19595f047e8173b5182fec0d5e"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b3646ced2eae3a0599658eeccc5ba7f303bf51b82514c50715bdd2b109e5ec"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3b75aea7c6cb91b341c85e7c1d9db1e09e1dd630b0717f836be94971e015031e"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5cfd14175f9db33d4b74d63de87c64bb0ee29ce475ce3c00c01ad2a3dc2a9e51"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-win32.whl", hash = "sha256:9031069d36cb949205293cf0e243abd5e64d6c93e01b078c37921493a41b72dc"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-win_amd64.whl", hash = "sha256:cc89b6c29f3dccbe12d7a3b3f1b3999db4882ae076c1c1f6df231d55dbd767a5"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:8de1b192c29b8ce45ee26a700044717bcbbd21c697fa1124d440548964328561"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:7e76accf38808f5c5c752b0ab3fd919eb14ff8fafb8db520ad1cc12afff74de6"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:d5658c3c2660417d82db51e168b277e0ff036d0b0f859fa7576c0ffd2aec1442"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5494d0e52bf77a2f7eb17c6da662886ca0a731e56c1c85b93505bece8dc6cf4c"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ed866f9edb574fd9be71bf64c954ce1b88fc93b2a4cbf94af221e9426eb14d6"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c5ba38aeac7a2fe353615c6b4213d1fbb3a3c34f86b4aaa8be08baaaee8cc56d"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f79e05f5bbf551c4057c227d1b041ace0e78462ac8128e2ad39ec58a382536d2"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-win32.whl", hash = "sha256:bf1f8be0da3fcdb2c1e9f374f3c2d043d606d69f425cd685110dd6d0d2d61258"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb9302afc3a0e4ba0b225cd651ef8e478bf0070cf11a529175caecd5ea2474e7"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:fc18a4de8c33491ad6f70022af5c460b39611e39578a4d84de0fe92f12d5d47b"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:0f0270bd9ffbff6961fe1da487bdcd594407ad390cc7960e738725d4807b18c4"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc48f99cc05e0698e689b51a05933253c69a8c8559a47f605cff83801b03af0e"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e925954b18d41aeb5ae250262116d0970893b38232689c4240024e4333ac084"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d222569273720366f68a99cb62e6194681eb763ee1d3b1005840678d4884f9"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b62b0f41e6e01a3e5082000b612064c87c93a49b05f7602fe1b7aa9fd5171a1d"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:db6f9fd2578dbe37db4b2994c94a1d9c93552ed77dca80e1657bb8a05b898b55"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-win32.whl", hash = "sha256:b192b81076073ed46f4b4dd612b8897d9a1e39d4eabd822e5da7b38497ed77e1"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-win_amd64.whl", hash = "sha256:1227ff7836f7b3a4ab04e5754f1d001fa52a730685d3dc894ed8bc262cc96c01"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:a78a06911d4081a24a1761d16215a08e9b6d4d29cdbb7e427e6c7e17b06bcc5d"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:dc5a351927d605b2721cbb46158e431dd49ce66ffbacb03e709dc07a491dde35"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:3629d8a8185f5139869a6a17865d03113a260e311e78fbe313f1a71603617589"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9a281878feeb9ae26db0622a19add03922a028d4db684658f16d546601a4870"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc614e895177ab7e4b70f154d1a7c97e152577ea101d76026d132b7aaba003b"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1ee76cd7e2e49cf9264f6812d8c9ac1b85dda0eaea063af07292400f9191750e"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0470fa911c503af59ec8bc4c82b371ee4303ececbbdc055f55ce48e38b20fd67"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-win32.whl", hash = "sha256:b650f34aceac8b2d08a4c8d7dc3e8a593f4d9e26d86751ebf74ebf5107d927de"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-win_amd64.whl", hash = "sha256:028337786f11fecb5d7b7fa660475a06aabf7e5e52b5ac2df47414878c0ce7ea"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:b7f693db593d6bf285e015d5538bf1c86cf9c60ed30b6f7da04a00ed052fe2f3"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:8b94e83f66dbf6fd642415faca0608590bc5e8d30e2c012b31d7d1b91b1de2fd"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:b634851b92c090763dde61df0868c730376cdb73a91bcc821af56ae043b09596"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf5f680d3ed08c15330d7830d06bc65f58ca40c9999309517fd62880d70cb06e"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:200e48a6e7b00f804cf00a1c26292a5baa96507c7749e70a3ec10ca1a288936e"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:45a4704339b6e5b24b0e136dea9ad3815a94f30eb4f1e1d44c4ac484ef11d8dd"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:85d347cb8237751b23539981dbd2d9d8f6e9ff90082b427b13022b948eb6347a"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-win32.whl", hash = "sha256:60e5de105dc02832dc8f120056306d0ef80932bcf1c0e2b4ca3b676de6dc6505"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-win_amd64.whl", hash = "sha256:282f47d0928e40f25d007f24eb8fa051cb22551e3c74b8248bc9f9bea9c35fe0"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:dd034d68a2905464c49479b0c209c773737a4245d616234c79c975c7c90eca03"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:01f834732c22a130bdf3dc154d1053bdbc887eb3ccb7f3e6285cfbfc33d9d5cc"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:a7f4ed0dcf202a70fe661329f8874bc3775c14bb3911d020d07c82c766ce0eb1"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd7ea241b10bc5f0bb0f82c0d7896822b7ed122b3ab35c9851b440c1ccf81588"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f03dc9b4da4c0dc8a1db7a5420f575251d7319b7a839004d8916257ddbe4816"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca71d73a270dff052fe4edf74fef142d6ddd1f84175d9ac4a14b7280572ac519"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ccbed100dc43704e94ccff9e07680b540d64e4cc89213ab2832b51b4f68a520"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-win32.whl", hash = "sha256:1514341def9c6ec4b7f0b9628be95f620f9d4b99331b7ef0a1845fd33d9b579c"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1fea55d26d647346acb0069b08dca70984101f2dc95066e003019207212e303"},
|
||||
{file = "grpcio-1.69.0.tar.gz", hash = "sha256:936fa44241b5379c5afc344e1260d467bee495747eaf478de825bab2791da6f5"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
protobuf = ["grpcio-tools (>=1.68.1)"]
|
||||
protobuf = ["grpcio-tools (>=1.69.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "grpcio-status"
|
||||
@@ -2805,13 +2806,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "huggingface-hub"
|
||||
version = "0.27.0"
|
||||
version = "0.27.1"
|
||||
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
|
||||
optional = false
|
||||
python-versions = ">=3.8.0"
|
||||
files = [
|
||||
{file = "huggingface_hub-0.27.0-py3-none-any.whl", hash = "sha256:8f2e834517f1f1ddf1ecc716f91b120d7333011b7485f665a9a412eacb1a2a81"},
|
||||
{file = "huggingface_hub-0.27.0.tar.gz", hash = "sha256:902cce1a1be5739f5589e560198a65a8edcfd3b830b1666f36e4b961f0454fac"},
|
||||
{file = "huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec"},
|
||||
{file = "huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2853,13 +2854,13 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.4"
|
||||
version = "2.6.5"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "identify-2.6.4-py2.py3-none-any.whl", hash = "sha256:993b0f01b97e0568c179bb9196391ff391bfb88a99099dbf5ce392b68f42d0af"},
|
||||
{file = "identify-2.6.4.tar.gz", hash = "sha256:285a7d27e397652e8cafe537a6cc97dd470a970f48fb2e9d979aa38eae5513ac"},
|
||||
{file = "identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566"},
|
||||
{file = "identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -2900,13 +2901,13 @@ test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "p
|
||||
|
||||
[[package]]
|
||||
name = "importlib-resources"
|
||||
version = "6.4.5"
|
||||
version = "6.5.2"
|
||||
description = "Read resources from Python packages"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"},
|
||||
{file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"},
|
||||
{file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"},
|
||||
{file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -3975,13 +3976,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "marshmallow"
|
||||
version = "3.23.2"
|
||||
version = "3.24.0"
|
||||
description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "marshmallow-3.23.2-py3-none-any.whl", hash = "sha256:bcaf2d6fd74fb1459f8450e85d994997ad3e70036452cbfa4ab685acb19479b3"},
|
||||
{file = "marshmallow-3.23.2.tar.gz", hash = "sha256:c448ac6455ca4d794773f00bae22c2f351d62d739929f761dce5eacb5c468d7f"},
|
||||
{file = "marshmallow-3.24.0-py3-none-any.whl", hash = "sha256:459922b7a1fd3d29d5082ddcadfcea0efd98985030e71d3ef0dd8f44f406e41d"},
|
||||
{file = "marshmallow-3.24.0.tar.gz", hash = "sha256:378572f727e52123d00de1bdd9b7ea7bed18bbfedc7f9bfbcddaf78925a8d602"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -3989,7 +3990,7 @@ packaging = ">=17.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["marshmallow[tests]", "pre-commit (>=3.5,<5.0)", "tox"]
|
||||
docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.14)", "sphinx (==8.1.3)", "sphinx-issues (==5.0.0)", "sphinx-version-warning (==1.1.2)"]
|
||||
docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.14)", "sphinx (==8.1.3)", "sphinx-issues (==5.0.0)"]
|
||||
tests = ["pytest", "simplejson"]
|
||||
|
||||
[[package]]
|
||||
@@ -4548,18 +4549,18 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=
|
||||
|
||||
[[package]]
|
||||
name = "nbconvert"
|
||||
version = "7.16.4"
|
||||
version = "7.16.5"
|
||||
description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "nbconvert-7.16.4-py3-none-any.whl", hash = "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3"},
|
||||
{file = "nbconvert-7.16.4.tar.gz", hash = "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4"},
|
||||
{file = "nbconvert-7.16.5-py3-none-any.whl", hash = "sha256:e12eac052d6fd03040af4166c563d76e7aeead2e9aadf5356db552a1784bd547"},
|
||||
{file = "nbconvert-7.16.5.tar.gz", hash = "sha256:c83467bb5777fdfaac5ebbb8e864f300b277f68692ecc04d6dab72f2d8442344"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
beautifulsoup4 = "*"
|
||||
bleach = "!=5.0.0"
|
||||
bleach = {version = "!=5.0.0", extras = ["css"]}
|
||||
defusedxml = "*"
|
||||
jinja2 = ">=3.0"
|
||||
jupyter-core = ">=4.7"
|
||||
@@ -4571,7 +4572,6 @@ nbformat = ">=5.7"
|
||||
packaging = "*"
|
||||
pandocfilters = ">=1.4.1"
|
||||
pygments = ">=2.4.1"
|
||||
tinycss2 = "*"
|
||||
traitlets = ">=5.1"
|
||||
|
||||
[package.extras]
|
||||
@@ -4727,13 +4727,13 @@ sympy = "*"
|
||||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "1.58.1"
|
||||
version = "1.59.3"
|
||||
description = "The official Python library for the openai API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "openai-1.58.1-py3-none-any.whl", hash = "sha256:e2910b1170a6b7f88ef491ac3a42c387f08bd3db533411f7ee391d166571d63c"},
|
||||
{file = "openai-1.58.1.tar.gz", hash = "sha256:f5a035fd01e141fc743f4b0e02c41ca49be8fab0866d3b67f5f29b4f4d3c0973"},
|
||||
{file = "openai-1.59.3-py3-none-any.whl", hash = "sha256:b041887a0d8f3e70d1fc6ffbb2bf7661c3b9a2f3e806c04bf42f572b9ac7bc37"},
|
||||
{file = "openai-1.59.3.tar.gz", hash = "sha256:7f7fff9d8729968588edf1524e73266e8593bb6cab09298340efb755755bb66f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5438,13 +5438,13 @@ testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "posthog"
|
||||
version = "3.7.4"
|
||||
version = "3.7.5"
|
||||
description = "Integrate PostHog into any python application."
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "posthog-3.7.4-py2.py3-none-any.whl", hash = "sha256:21c18c6bf43b2de303ea4cd6e95804cc0f24c20cb2a96a8fd09da2ed50b62faa"},
|
||||
{file = "posthog-3.7.4.tar.gz", hash = "sha256:19384bd09d330f9787a7e2446aba14c8057ece56144970ea2791072d4e40cd36"},
|
||||
{file = "posthog-3.7.5-py2.py3-none-any.whl", hash = "sha256:022132c17069dde03c5c5904e2ae1b9bd68d5059cbc5a8dffc5c1537a1b71cb5"},
|
||||
{file = "posthog-3.7.5.tar.gz", hash = "sha256:8ba40ab623da35db72715fc87fe7dccb7fc272ced92581fe31db2d4dbe7ad761"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5488,13 +5488,13 @@ selenium = ">=4.18.1,<5.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.14"
|
||||
version = "0.0.23"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "praisonaiagents-0.0.14-py3-none-any.whl", hash = "sha256:6d239d91911ca289aa7be0badebc7c18e187bdae7dc9248072a8c570fe0fbeef"},
|
||||
{file = "praisonaiagents-0.0.14.tar.gz", hash = "sha256:1acb94dc5e2fa677f922e0d3d23df0748f02982ebb52d3309c5f2295e49b39cc"},
|
||||
{file = "praisonaiagents-0.0.23-py3-none-any.whl", hash = "sha256:d6aaa406fc993ccd0a763aa426b7139c955e1cd99e6b204b06817ebc1a5855e3"},
|
||||
{file = "praisonaiagents-0.0.23.tar.gz", hash = "sha256:1814d537b2625a5c7d4b61d07f5d5bd043f0ad8afc31fe9d4eb99a5ca54101bf"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5522,20 +5522,20 @@ virtualenv = ">=20.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "primp"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "primp-0.9.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:a3179640e633be843ed5daba5c4e3086ad91f77c7bb40a9db06326f28d56b12b"},
|
||||
{file = "primp-0.9.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:94a5da8ba25f74152b43bc16a7591dfb5d7d30a5827dc0a0f96a956f7d3616be"},
|
||||
{file = "primp-0.9.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0668c0abb6d56fc8b0a918179b1d0f68e7267c1dc632e2b683c618317e13143f"},
|
||||
{file = "primp-0.9.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:a9c29a4b8eabfc28a1746d2fe93d33b9fcf2e81e642dd0e3eaecede60cc36b7d"},
|
||||
{file = "primp-0.9.2-cp38-abi3-manylinux_2_34_armv7l.whl", hash = "sha256:04d499308a101b06b40f5fda1bdc795db5731cd0dfbb1a8873f4acd07c085b1d"},
|
||||
{file = "primp-0.9.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4cd5daf39034a0a8c96cdc0c4c306184c6f2b1b2a0b39dc3294d79ed28a6f7fe"},
|
||||
{file = "primp-0.9.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8d14653434837eb431b3cf7ca006647d7a196906e48bba96bb600ba2ba70bcdc"},
|
||||
{file = "primp-0.9.2-cp38-abi3-win_amd64.whl", hash = "sha256:80d9f07564dc9b25b1a9676df770561418557c124fedecae84f6491a1974b61d"},
|
||||
{file = "primp-0.9.2.tar.gz", hash = "sha256:5b95666c25b9107eab3c05a89cb7b1748d5122e57c57b25bfc3249d525c45300"},
|
||||
{file = "primp-0.9.3-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:30d5c4f03abeab8fd307ddf4c615d8d093367f3be1a5299078f811982db7cb6f"},
|
||||
{file = "primp-0.9.3-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:3e3bff0bcffdf746b68486db24ac6dc6db2f202f048f82e0303385ef76dc5c1e"},
|
||||
{file = "primp-0.9.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15325ec0b916e48a65929f647d7dd12fb1400e76a6aeba72f7e205c94c4aaa82"},
|
||||
{file = "primp-0.9.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:de97cc10130a68edcd4e173cf01c628a10b9b6a6e19393200b12f1a1ddcb863d"},
|
||||
{file = "primp-0.9.3-cp38-abi3-manylinux_2_34_armv7l.whl", hash = "sha256:cba94e48c9b245a9daac96807aa020525c1a66c1141d4c2b11db4e2ccb69da33"},
|
||||
{file = "primp-0.9.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1d1df5a9808b82b960df1f72ff53a9ab9c77dce61fcbe5776a11cf5f59dd7f28"},
|
||||
{file = "primp-0.9.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:484fc69dbed5ca14561d54aecd17f011c8ffa495023134bb9a94edb808ae3e1b"},
|
||||
{file = "primp-0.9.3-cp38-abi3-win_amd64.whl", hash = "sha256:824a5606ad67cb842ccc5158f19f9ccd1387e25e1374edd69f87cd7616cf3ea9"},
|
||||
{file = "primp-0.9.3.tar.gz", hash = "sha256:bc6490c659c741c6586bd160ed51b2e04f9dbc3b61bc1dd1af1ce66eefea663e"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -6161,13 +6161,13 @@ requests = ">=2.14.0"
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.18.0"
|
||||
version = "2.19.1"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
|
||||
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
|
||||
{file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"},
|
||||
{file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -7168,29 +7168,29 @@ pyasn1 = ">=0.1.3"
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.8.4"
|
||||
version = "0.8.6"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"},
|
||||
{file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"},
|
||||
{file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"},
|
||||
{file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"},
|
||||
{file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"},
|
||||
{file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"},
|
||||
{file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"},
|
||||
{file = "ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3"},
|
||||
{file = "ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1"},
|
||||
{file = "ruff-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e88b8f6d901477c41559ba540beeb5a671e14cd29ebd5683903572f4b40a9807"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0509e8da430228236a18a677fcdb0c1f102dd26d5520f71f79b094963322ed25"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a7ddb221779871cf226100e677b5ea38c2d54e9e2c8ed847450ebbdf99b32d"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248b1fb3f739d01d528cc50b35ee9c4812aa58cc5935998e776bf8ed5b251e75"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bc3c083c50390cf69e7e1b5a5a7303898966be973664ec0c4a4acea82c1d4315"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52d587092ab8df308635762386f45f4638badb0866355b2b86760f6d3c076188"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61323159cf21bc3897674e5adb27cd9e7700bab6b84de40d7be28c3d46dc67cf"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae4478b1471fc0c44ed52a6fb787e641a2ac58b1c1f91763bafbc2faddc5117"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0c000a471d519b3e6cfc9c6680025d923b4ca140ce3e4612d1a2ef58e11f11fe"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9257aa841e9e8d9b727423086f0fa9a86b6b420fbf4bf9e1465d1250ce8e4d8d"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45a56f61b24682f6f6709636949ae8cc82ae229d8d773b4c76c09ec83964a95a"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:496dd38a53aa173481a7d8866bcd6451bd934d06976a2505028a50583e001b76"},
|
||||
{file = "ruff-0.8.6-py3-none-win32.whl", hash = "sha256:e169ea1b9eae61c99b257dc83b9ee6c76f89042752cb2d83486a7d6e48e8f764"},
|
||||
{file = "ruff-0.8.6-py3-none-win_amd64.whl", hash = "sha256:f1d70bef3d16fdc897ee290d7d20da3cbe4e26349f62e8a0274e7a3f4ce7a905"},
|
||||
{file = "ruff-0.8.6-py3-none-win_arm64.whl", hash = "sha256:7d7fc2377a04b6e04ffe588caad613d0c460eb2ecba4c0ccbbfe2bc973cbc162"},
|
||||
{file = "ruff-0.8.6.tar.gz", hash = "sha256:dcad24b81b62650b0eb8814f576fc65cfee8674772a6e24c9b747911801eeaa5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7263,53 +7263,60 @@ tests = ["black (>=24.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.9)", "numpydoc (
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.14.1"
|
||||
version = "1.15.0"
|
||||
description = "Fundamental algorithms for scientific computing in Python"
|
||||
optional = true
|
||||
python-versions = ">=3.10"
|
||||
files = [
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84"},
|
||||
{file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:aeac60d3562a7bf2f35549bdfdb6b1751c50590f55ce7322b4b2fc821dc27fca"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5abbdc6ede5c5fed7910cf406a948e2c0869231c0db091593a6b2fa78be77e5d"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:eb1533c59f0ec6c55871206f15a5c72d1fae7ad3c0a8ca33ca88f7c309bbbf8c"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:de112c2dae53107cfeaf65101419662ac0a54e9a088c17958b51c95dac5de56d"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2240e1fd0782e62e1aacdc7234212ee271d810f67e9cd3b8d521003a82603ef8"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d35aef233b098e4de88b1eac29f0df378278e7e250a915766786b773309137c4"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b29e4fc02e155a5fd1165f1e6a73edfdd110470736b0f48bcbe48083f0eee37"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:0e5b34f8894f9904cc578008d1a9467829c1817e9f9cb45e6d6eeb61d2ab7731"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:46e91b5b16909ff79224b56e19cbad65ca500b3afda69225820aa3afbf9ec020"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:82bff2eb01ccf7cea8b6ee5274c2dbeadfdac97919da308ee6d8e5bcbe846443"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:9c8254fe21dd2c6c8f7757035ec0c31daecf3bb3cffd93bc1ca661b731d28136"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:c9624eeae79b18cab1a31944b5ef87aa14b125d6ab69b71db22f0dbd962caf1e"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d13bbc0658c11f3d19df4138336e4bce2c4fbd78c2755be4bf7b8e235481557f"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdca4c7bb8dc41307e5f39e9e5d19c707d8e20a29845e7533b3bb20a9d4ccba0"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f376d7c767731477bac25a85d0118efdc94a572c6b60decb1ee48bf2391a73b"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:61513b989ee8d5218fbeb178b2d51534ecaddba050db949ae99eeb3d12f6825d"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5beb0a2200372b7416ec73fdae94fe81a6e85e44eb49c35a11ac356d2b8eccc6"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fde0f3104dfa1dfbc1f230f65506532d0558d43188789eaf68f97e106249a913"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:35c68f7044b4e7ad73a3e68e513dda946989e523df9b062bd3cf401a1a882192"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:52475011be29dfcbecc3dfe3060e471ac5155d72e9233e8d5616b84e2b542054"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5972e3f96f7dda4fd3bb85906a17338e65eaddfe47f750e240f22b331c08858e"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe00169cf875bed0b3c40e4da45b57037dc21d7c7bf0c85ed75f210c281488f1"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:161f80a98047c219c257bf5ce1777c574bde36b9d962a46b20d0d7e531f86863"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:327163ad73e54541a675240708244644294cb0a65cca420c9c79baeb9648e479"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0fcb16eb04d84670722ce8d93b05257df471704c913cb0ff9dc5a1c31d1e9422"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:767e8cf6562931f8312f4faa7ddea412cb783d8df49e62c44d00d89f41f9bbe8"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:37ce9394cdcd7c5f437583fc6ef91bd290014993900643fdfc7af9b052d1613b"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6d26f17c64abd6c6c2dfb39920f61518cc9e213d034b45b2380e32ba78fde4c0"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e2448acd79c6374583581a1ded32ac71a00c2b9c62dfa87a40e1dd2520be111"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36be480e512d38db67f377add5b759fb117edd987f4791cdf58e59b26962bee4"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ccb6248a9987193fe74363a2d73b93bc2c546e0728bd786050b7aef6e17db03c"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:952d2e9eaa787f0a9e95b6e85da3654791b57a156c3e6609e65cc5176ccfe6f2"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b1432102254b6dc7766d081fa92df87832ac25ff0b3d3a940f37276e63eb74ff"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:4e08c6a36f46abaedf765dd2dfcd3698fa4bd7e311a9abb2d80e33d9b2d72c34"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ec915cd26d76f6fc7ae8522f74f5b2accf39546f341c771bb2297f3871934a52"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:351899dd2a801edd3691622172bc8ea01064b1cada794f8641b89a7dc5418db6"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9baff912ea4f78a543d183ed6f5b3bea9784509b948227daaf6f10727a0e2e5"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cd9d9198a7fd9a77f0eb5105ea9734df26f41faeb2a88a0e62e5245506f7b6df"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:129f899ed275c0515d553b8d31696924e2ca87d1972421e46c376b9eb87de3d2"},
|
||||
{file = "scipy-1.15.0.tar.gz", hash = "sha256:300742e2cc94e36a2880ebe464a1c8b4352a7b0f3e36ec3d2ac006cdbe0219ac"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
numpy = ">=1.23.5,<2.3"
|
||||
numpy = ">=1.23.5,<2.5"
|
||||
|
||||
[package.extras]
|
||||
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
|
||||
doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"]
|
||||
test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
|
||||
doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.16.5)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
|
||||
test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
|
||||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
@@ -7358,23 +7365,23 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "75.6.0"
|
||||
version = "75.7.0"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"},
|
||||
{file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"},
|
||||
{file = "setuptools-75.7.0-py3-none-any.whl", hash = "sha256:84fb203f278ebcf5cd08f97d3fb96d3fbed4b629d500b29ad60d11e00769b183"},
|
||||
{file = "setuptools-75.7.0.tar.gz", hash = "sha256:886ff7b16cd342f1d1defc16fc98c9ce3fde69e087a4e1983d7ab634e5f41f4f"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
|
||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"]
|
||||
core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
|
||||
cover = ["pytest-cov"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
|
||||
enabler = ["pytest-enabler (>=2.2)"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
|
||||
type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
|
||||
type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"]
|
||||
|
||||
[[package]]
|
||||
name = "shapely"
|
||||
@@ -8271,13 +8278,13 @@ test = ["aiohttp (>=3.10.5)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil",
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.28.0"
|
||||
version = "20.28.1"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"},
|
||||
{file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"},
|
||||
{file = "virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb"},
|
||||
{file = "virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -8822,9 +8829,9 @@ gradio = ["gradio"]
|
||||
openai = ["langchain-openai"]
|
||||
realtime = ["aiosqlite", "chainlit", "crawl4ai", "duckduckgo_search", "greenlet", "litellm", "plotly", "sqlalchemy", "tavily-python", "websockets", "yfinance"]
|
||||
train = []
|
||||
ui = ["chainlit"]
|
||||
ui = ["aiosqlite", "chainlit", "greenlet", "pydantic", "sqlalchemy"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.10,<3.13"
|
||||
content-hash = "eb9727e6cb210753564b5c109a9e353f65d5f4c79889e0a3c4e8ce5080ee23e4"
|
||||
content-hash = "596dee1ab307caacfd8041e13a29b60d0b793274e7ea45890b827a92e8c2dd40"
|
||||
@@ -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.20.tar.gz"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.32.tar.gz"
|
||||
sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum
|
||||
license "MIT"
|
||||
|
||||
|
||||
@@ -478,7 +478,7 @@ class PraisonAI:
|
||||
logging.info("Public folder not found in the package.")
|
||||
else:
|
||||
logging.info("Public folder already exists.")
|
||||
chainlit_ui_path = os.path.join(os.path.dirname(praisonai.__file__), 'chainlit_ui.py')
|
||||
chainlit_ui_path = os.path.join(os.path.dirname(praisonai.__file__), 'ui', 'agents.py')
|
||||
chainlit_run([chainlit_ui_path])
|
||||
else:
|
||||
print("ERROR: Chainlit is not installed. Please install it with 'pip install \"praisonai[ui]\"' to use the UI.")
|
||||
|
||||
@@ -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.20 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.32 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 168 KiB |
|
After Width: | Height: | Size: 167 KiB |
@@ -0,0 +1,822 @@
|
||||
from chainlit.input_widget import Select, TextInput
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
import logging
|
||||
import inspect
|
||||
import chainlit as cl
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, register_display_callback
|
||||
|
||||
framework = "praisonai"
|
||||
config_list = [
|
||||
{
|
||||
'model': os.environ.get("OPENAI_MODEL_NAME", "gpt-4o"),
|
||||
'base_url': os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
|
||||
'api_key': os.environ.get("OPENAI_API_KEY", "")
|
||||
}
|
||||
]
|
||||
|
||||
actions = [
|
||||
cl.Action(name="run", value="run", label="✅ Run"),
|
||||
cl.Action(name="modify", value="modify", label="🔧 Modify"),
|
||||
]
|
||||
|
||||
@cl.action_callback("run")
|
||||
async def on_run(action):
|
||||
await main(cl.Message(content=""))
|
||||
|
||||
@cl.action_callback("modify")
|
||||
async def on_modify(action):
|
||||
await cl.Message(content="Modify the agents and tools from below settings").send()
|
||||
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
import logging
|
||||
import inspect
|
||||
import asyncio
|
||||
import importlib.util
|
||||
import sqlite3
|
||||
from queue import Queue
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Chainlit imports
|
||||
import chainlit as cl
|
||||
from chainlit.types import ThreadDict
|
||||
import chainlit.data as cl_data
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Global Setup
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
load_dotenv()
|
||||
log_level = os.getenv("LOGLEVEL", "INFO").upper()
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(log_level)
|
||||
|
||||
message_queue = Queue() # Queue to handle messages sent to Chainlit UI
|
||||
agent_file = "agents.yaml"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Database and Settings Logic
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
MAX_RETRIES = 3
|
||||
RETRY_DELAY = 1 # seconds
|
||||
|
||||
from db import DatabaseManager
|
||||
|
||||
async def init_database_with_retry():
|
||||
db = DatabaseManager()
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
db.initialize()
|
||||
return db
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e) and attempt < MAX_RETRIES - 1:
|
||||
await asyncio.sleep(RETRY_DELAY)
|
||||
continue
|
||||
raise
|
||||
|
||||
db_manager = asyncio.run(init_database_with_retry())
|
||||
cl_data._data_layer = db_manager
|
||||
|
||||
async def save_setting_with_retry(key: str, value: str):
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
await db_manager.save_setting(key, value)
|
||||
return
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e) and attempt < MAX_RETRIES - 1:
|
||||
await asyncio.sleep(RETRY_DELAY)
|
||||
continue
|
||||
raise
|
||||
|
||||
async def load_setting_with_retry(key: str) -> str:
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
return await db_manager.load_setting(key)
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e) and attempt < MAX_RETRIES - 1:
|
||||
await asyncio.sleep(RETRY_DELAY)
|
||||
continue
|
||||
raise
|
||||
return ""
|
||||
|
||||
def save_setting(key: str, value: str):
|
||||
asyncio.run(save_setting_with_retry(key, value))
|
||||
|
||||
def load_setting(key: str) -> str:
|
||||
return asyncio.run(load_setting_with_retry(key))
|
||||
|
||||
async def update_thread_metadata(thread_id: str, metadata: dict):
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
await cl_data.update_thread(thread_id, metadata=metadata)
|
||||
return
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e) and attempt < MAX_RETRIES - 1:
|
||||
await asyncio.sleep(RETRY_DELAY)
|
||||
continue
|
||||
raise
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Callback Manager
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
class CallbackManager:
|
||||
def __init__(self):
|
||||
self._callbacks = {}
|
||||
|
||||
def register(self, name: str, callback, is_async: bool = False) -> None:
|
||||
self._callbacks[name] = {'func': callback, 'is_async': is_async}
|
||||
|
||||
async def call(self, name: str, **kwargs) -> None:
|
||||
if name not in self._callbacks:
|
||||
logger.warning(f"No callback registered for {name}")
|
||||
return
|
||||
callback_info = self._callbacks[name]
|
||||
func = callback_info['func']
|
||||
is_async = callback_info['is_async']
|
||||
try:
|
||||
if is_async:
|
||||
await func(**kwargs)
|
||||
else:
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
await func(**kwargs)
|
||||
else:
|
||||
await asyncio.get_event_loop().run_in_executor(None, lambda: func(**kwargs))
|
||||
except Exception as e:
|
||||
logger.error(f"Error in callback {name}: {str(e)}")
|
||||
|
||||
callback_manager = CallbackManager()
|
||||
|
||||
def register_callback(name: str, callback, is_async: bool = False) -> None:
|
||||
callback_manager.register(name, callback, is_async)
|
||||
|
||||
async def trigger_callback(name: str, **kwargs) -> None:
|
||||
await callback_manager.call(name, **kwargs)
|
||||
|
||||
def callback(name: str, is_async: bool = False):
|
||||
def decorator(func):
|
||||
register_callback(name, func, is_async)
|
||||
return func
|
||||
return decorator
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# ADDITIONAL CALLBACKS
|
||||
# -----------------------------------------------------------------------------
|
||||
def interaction_callback(message=None, response=None, **kwargs):
|
||||
logger.debug(f"[CALLBACK: interaction] Message: {message} | Response: {response}")
|
||||
message_queue.put({
|
||||
"content": f"[CALLBACK: interaction] Message: {message} | Response: {response}",
|
||||
"author": "Callback"
|
||||
})
|
||||
|
||||
def error_callback(message=None, **kwargs):
|
||||
logger.error(f"[CALLBACK: error] Message: {message}")
|
||||
message_queue.put({
|
||||
"content": f"[CALLBACK: error] Message: {message}",
|
||||
"author": "Callback"
|
||||
})
|
||||
|
||||
def tool_call_callback(message=None, **kwargs):
|
||||
logger.debug(f"[CALLBACK: tool_call] Tool used: {message}")
|
||||
message_queue.put({
|
||||
"content": f"[CALLBACK: tool_call] Tool used: {message}",
|
||||
"author": "Callback"
|
||||
})
|
||||
|
||||
def instruction_callback(message=None, **kwargs):
|
||||
logger.debug(f"[CALLBACK: instruction] Instruction: {message}")
|
||||
message_queue.put({
|
||||
"content": f"[CALLBACK: instruction] Instruction: {message}",
|
||||
"author": "Callback"
|
||||
})
|
||||
|
||||
def self_reflection_callback(message=None, **kwargs):
|
||||
logger.debug(f"[CALLBACK: self_reflection] Reflection: {message}")
|
||||
message_queue.put({
|
||||
"content": f"[CALLBACK: self_reflection] Reflection: {message}",
|
||||
"author": "Callback"
|
||||
})
|
||||
|
||||
register_display_callback('error', error_callback)
|
||||
register_display_callback('tool_call', tool_call_callback)
|
||||
register_display_callback('instruction', instruction_callback)
|
||||
register_display_callback('self_reflection', self_reflection_callback)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Tools Loader
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def load_tools_from_tools_py():
|
||||
"""
|
||||
Imports and returns all contents from tools.py file.
|
||||
Also adds the tools to the global namespace.
|
||||
"""
|
||||
tools_dict = {}
|
||||
try:
|
||||
spec = importlib.util.spec_from_file_location("tools", "tools.py")
|
||||
if spec is None:
|
||||
logger.info("tools.py not found in current directory")
|
||||
return tools_dict
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
for name, obj in inspect.getmembers(module):
|
||||
if not name.startswith('_') and callable(obj) and not inspect.isclass(obj):
|
||||
# Store the function in globals
|
||||
globals()[name] = obj
|
||||
|
||||
# Build the function definition
|
||||
tool_def = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": name,
|
||||
"description": obj.__doc__ or f"Function to {name.replace('_', ' ')}",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
},
|
||||
# Keep the actual callable as well
|
||||
"callable": obj,
|
||||
}
|
||||
|
||||
tools_dict[name] = tool_def
|
||||
logger.info(f"Loaded and globalized tool function: {name}")
|
||||
|
||||
logger.info(f"Loaded {len(tools_dict)} tool functions from tools.py")
|
||||
except Exception as e:
|
||||
logger.warning(f"Error loading tools from tools.py: {e}")
|
||||
return tools_dict
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Async Queue Processor
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
async def process_message_queue():
|
||||
while True:
|
||||
try:
|
||||
if not message_queue.empty():
|
||||
msg_data = message_queue.get()
|
||||
await cl.Message(**msg_data).send()
|
||||
await asyncio.sleep(0.1)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing message queue: {e}")
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Step & Task Callbacks
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
async def step_callback(step_details):
|
||||
logger.info(f"[CALLBACK DEBUG] step_callback: {step_details}")
|
||||
agent_name = step_details.get("agent_name", "Agent")
|
||||
try:
|
||||
if step_details.get("response"):
|
||||
message_queue.put({
|
||||
"content": f"Agent Response: {step_details['response']}",
|
||||
"author": agent_name
|
||||
})
|
||||
if step_details.get("tool_name"):
|
||||
message_queue.put({
|
||||
"content": f"🛠️ Using tool: {step_details['tool_name']}",
|
||||
"author": "System"
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Error in step_callback: {e}", exc_info=True)
|
||||
|
||||
async def task_callback(task_output):
|
||||
logger.info(f"[CALLBACK DEBUG] task_callback: type={type(task_output)}")
|
||||
try:
|
||||
if hasattr(task_output, 'raw'):
|
||||
content = task_output.raw
|
||||
elif hasattr(task_output, 'content'):
|
||||
content = task_output.content
|
||||
else:
|
||||
content = str(task_output)
|
||||
message_queue.put({
|
||||
"content": f"Task Output: {content}",
|
||||
"author": "Task"
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Error in task_callback: {e}", exc_info=True)
|
||||
|
||||
async def step_callback_wrapper(step_details):
|
||||
logger.info(f"[CALLBACK DEBUG] step_callback_wrapper: {step_details}")
|
||||
agent_name = step_details.get("agent_name", "Agent")
|
||||
try:
|
||||
if not cl.context.context_var.get():
|
||||
logger.warning("[CALLBACK DEBUG] No Chainlit context in wrapper.")
|
||||
return
|
||||
if step_details.get("response"):
|
||||
await cl.Message(
|
||||
content=f"{agent_name}: {step_details['response']}",
|
||||
author=agent_name,
|
||||
).send()
|
||||
if step_details.get("tool_name"):
|
||||
await cl.Message(
|
||||
content=f"🛠️ {agent_name} is using tool: {step_details['tool_name']}",
|
||||
author="System",
|
||||
).send()
|
||||
if step_details.get("thought"):
|
||||
await cl.Message(
|
||||
content=f"💭 {agent_name}'s thought: {step_details['thought']}",
|
||||
author=agent_name,
|
||||
).send()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in step_callback_wrapper: {e}", exc_info=True)
|
||||
try:
|
||||
await cl.Message(content=f"Error in step callback: {e}", author="System").send()
|
||||
except Exception as send_error:
|
||||
logger.error(f"Error sending error message: {send_error}")
|
||||
|
||||
async def task_callback_wrapper(task_output):
|
||||
logger.info("[CALLBACK DEBUG] task_callback_wrapper triggered")
|
||||
try:
|
||||
if not cl.context.context_var.get():
|
||||
logger.warning("[CALLBACK DEBUG] No Chainlit context in task wrapper.")
|
||||
return
|
||||
if hasattr(task_output, 'raw'):
|
||||
content = task_output.raw
|
||||
elif hasattr(task_output, 'content'):
|
||||
content = task_output.content
|
||||
else:
|
||||
content = str(task_output)
|
||||
|
||||
await cl.Message(
|
||||
content=f"✅ Agent completed task:\n{content}",
|
||||
author="Agent",
|
||||
).send()
|
||||
|
||||
if hasattr(task_output, 'details'):
|
||||
await cl.Message(
|
||||
content=f"📝 Additional details:\n{task_output.details}",
|
||||
author="Agent",
|
||||
).send()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in task_callback_wrapper: {e}", exc_info=True)
|
||||
try:
|
||||
await cl.Message(content=f"Error in task callback: {e}", author="System").send()
|
||||
except Exception as send_error:
|
||||
logger.error(f"Error sending error message: {send_error}")
|
||||
|
||||
def sync_task_callback_wrapper(task_output):
|
||||
logger.info("[CALLBACK DEBUG] sync_task_callback_wrapper")
|
||||
try:
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
if loop.is_running():
|
||||
asyncio.run_coroutine_threadsafe(task_callback_wrapper(task_output), loop)
|
||||
else:
|
||||
loop.run_until_complete(task_callback_wrapper(task_output))
|
||||
except Exception as e:
|
||||
logger.error(f"Error in sync_task_callback_wrapper: {e}", exc_info=True)
|
||||
|
||||
def sync_step_callback_wrapper(step_details):
|
||||
logger.info("[CALLBACK DEBUG] sync_step_callback_wrapper")
|
||||
try:
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
if loop.is_running():
|
||||
asyncio.run_coroutine_threadsafe(step_callback_wrapper(step_details), loop)
|
||||
else:
|
||||
loop.run_until_complete(step_callback_wrapper(step_details))
|
||||
except Exception as e:
|
||||
logger.error(f"Error in sync_step_callback_wrapper: {e}", exc_info=True)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Main PraisonAI Runner
|
||||
# -----------------------------------------------------------------------------
|
||||
async def ui_run_praisonai(config, topic, tools_dict):
|
||||
logger.info("Starting ui_run_praisonai")
|
||||
agents_map = {}
|
||||
tasks = []
|
||||
tasks_dict = {}
|
||||
|
||||
try:
|
||||
queue_processor = asyncio.create_task(process_message_queue())
|
||||
|
||||
# Create agents
|
||||
for role, details in config['roles'].items():
|
||||
role_name = details.get('name', role).format(topic=topic)
|
||||
role_filled = details.get('role', role).format(topic=topic)
|
||||
goal_filled = details['goal'].format(topic=topic)
|
||||
backstory_filled = details['backstory'].format(topic=topic)
|
||||
|
||||
def step_callback_sync(step_details):
|
||||
step_details["agent_name"] = role_name
|
||||
try:
|
||||
loop_ = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop_)
|
||||
loop_.run_until_complete(step_callback(step_details))
|
||||
loop_.close()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in step_callback_sync: {e}", exc_info=True)
|
||||
|
||||
agent = Agent(
|
||||
name=role_name,
|
||||
role=role_filled,
|
||||
goal=goal_filled,
|
||||
backstory=backstory_filled,
|
||||
llm=details.get('llm', 'gpt-4o'),
|
||||
verbose=True,
|
||||
allow_delegation=details.get('allow_delegation', False),
|
||||
max_iter=details.get('max_iter', 15),
|
||||
max_rpm=details.get('max_rpm'),
|
||||
max_execution_time=details.get('max_execution_time'),
|
||||
cache=details.get('cache', True),
|
||||
step_callback=step_callback_sync,
|
||||
self_reflect=details.get('self_reflect', False)
|
||||
)
|
||||
agents_map[role] = agent
|
||||
|
||||
# Create tasks
|
||||
for role, details in config['roles'].items():
|
||||
agent = agents_map[role]
|
||||
role_name = agent.name
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# FIX: Skip empty or invalid tool names to avoid null tool objects
|
||||
# -------------------------------------------------------------
|
||||
role_tools = []
|
||||
task_tools = [] # Initialize task_tools outside the loop
|
||||
|
||||
for tool_name in details.get('tools', []):
|
||||
if not tool_name or not tool_name.strip():
|
||||
logger.warning("Skipping empty tool name.")
|
||||
continue
|
||||
if tool_name in tools_dict:
|
||||
# Create a copy of the tool definition
|
||||
tool_def = tools_dict[tool_name].copy()
|
||||
# Store the callable separately and remove from definition
|
||||
callable_func = tool_def.pop("callable")
|
||||
# Add callable to role_tools for task execution
|
||||
role_tools.append(callable_func)
|
||||
# Add API tool definition to task's tools
|
||||
task_tools.append(tool_def)
|
||||
# Also set the agent's tools to include both
|
||||
agent.tools = role_tools
|
||||
else:
|
||||
logger.warning(f"Tool '{tool_name}' not found. Skipping.")
|
||||
|
||||
for tname, tdetails in details.get('tasks', {}).items():
|
||||
description_filled = tdetails['description'].format(topic=topic)
|
||||
expected_output_filled = tdetails['expected_output'].format(topic=topic)
|
||||
|
||||
def task_callback_sync(task_output):
|
||||
try:
|
||||
loop_ = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop_)
|
||||
loop_.run_until_complete(task_callback(task_output))
|
||||
loop_.close()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in task_callback_sync: {e}", exc_info=True)
|
||||
|
||||
task = Task(
|
||||
description=description_filled,
|
||||
expected_output=expected_output_filled,
|
||||
agent=agent,
|
||||
tools=task_tools, # Pass API tool definitions
|
||||
async_execution=True,
|
||||
context=[],
|
||||
config=tdetails.get('config', {}),
|
||||
output_json=tdetails.get('output_json'),
|
||||
output_pydantic=tdetails.get('output_pydantic'),
|
||||
output_file=tdetails.get('output_file', ""),
|
||||
callback=task_callback_sync,
|
||||
create_directory=tdetails.get('create_directory', False)
|
||||
)
|
||||
tasks.append(task)
|
||||
tasks_dict[tname] = task
|
||||
|
||||
# Build context links
|
||||
for role, details in config['roles'].items():
|
||||
for tname, tdetails in details.get('tasks', {}).items():
|
||||
if tname not in tasks_dict:
|
||||
continue
|
||||
task = tasks_dict[tname]
|
||||
context_tasks = [
|
||||
tasks_dict[ctx]
|
||||
for ctx in tdetails.get('context', [])
|
||||
if ctx in tasks_dict
|
||||
]
|
||||
task.context = context_tasks
|
||||
|
||||
await cl.Message(content="Starting PraisonAI agents execution...", author="System").send()
|
||||
|
||||
# Decide how to process tasks
|
||||
if config.get('process') == 'hierarchical':
|
||||
prai_agents = PraisonAIAgents(
|
||||
agents=list(agents_map.values()),
|
||||
tasks=tasks,
|
||||
verbose=True,
|
||||
process="hierarchical",
|
||||
manager_llm=config.get('manager_llm', 'gpt-4o')
|
||||
)
|
||||
else:
|
||||
prai_agents = PraisonAIAgents(
|
||||
agents=list(agents_map.values()),
|
||||
tasks=tasks,
|
||||
verbose=2
|
||||
)
|
||||
|
||||
cl.user_session.set("agents", prai_agents)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
response = await loop.run_in_executor(None, prai_agents.start)
|
||||
|
||||
if hasattr(response, 'raw'):
|
||||
result = response.raw
|
||||
elif hasattr(response, 'content'):
|
||||
result = response.content
|
||||
else:
|
||||
result = str(response)
|
||||
|
||||
await cl.Message(content="PraisonAI agents execution completed.", author="System").send()
|
||||
await asyncio.sleep(1)
|
||||
queue_processor.cancel()
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error in ui_run_praisonai: {str(e)}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
await cl.Message(content=error_msg, author="System").send()
|
||||
raise
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Chainlit Handlers + logic
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
tools_dict = load_tools_from_tools_py()
|
||||
print(f"[DEBUG] tools_dict: {tools_dict}")
|
||||
|
||||
# Load agent config (default) from 'agents.yaml'
|
||||
with open(agent_file, 'r') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
AUTH_PASSWORD_ENABLED = os.getenv("AUTH_PASSWORD_ENABLED", "true").lower() == "true"
|
||||
CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
|
||||
if not CHAINLIT_AUTH_SECRET:
|
||||
os.environ["CHAINLIT_AUTH_SECRET"] = "p8BPhQChpg@J>jBz$wGxqLX2V>yTVgP*7Ky9H$aV:axW~ANNX-7_T:o@lnyCBu^U"
|
||||
|
||||
username_env = os.getenv("CHAINLIT_USERNAME", "admin")
|
||||
password_env = os.getenv("CHAINLIT_PASSWORD", "admin")
|
||||
|
||||
def simple_auth_callback(u: str, p: str):
|
||||
if (u, p) == (username_env, password_env):
|
||||
return cl.User(identifier=u, metadata={"role": "ADMIN", "provider": "credentials"})
|
||||
return None
|
||||
|
||||
if AUTH_PASSWORD_ENABLED:
|
||||
auth_callback = cl.password_auth_callback(simple_auth_callback)
|
||||
|
||||
@cl.set_chat_profiles
|
||||
async def set_profiles(current_user: cl.User):
|
||||
return [
|
||||
cl.ChatProfile(
|
||||
name="Auto",
|
||||
markdown_description=(
|
||||
"Automatically generate agents and tasks based on your input."
|
||||
),
|
||||
starters=[
|
||||
cl.Starter(
|
||||
label="Create a movie script",
|
||||
message=(
|
||||
"Create a movie script about a futuristic society where AI "
|
||||
"and humans coexist, focusing on the conflict and resolution "
|
||||
"between them. Start with an intriguing opening scene."
|
||||
),
|
||||
icon="/public/movie.svg",
|
||||
),
|
||||
cl.Starter(
|
||||
label="Design a fantasy world",
|
||||
message=(
|
||||
"Design a detailed fantasy world with unique geography, "
|
||||
"cultures, and magical systems. Start by describing the main "
|
||||
"continent and its inhabitants."
|
||||
),
|
||||
icon="/public/fantasy.svg",
|
||||
),
|
||||
cl.Starter(
|
||||
label="Write a futuristic political thriller",
|
||||
message=(
|
||||
"Write a futuristic political thriller involving a conspiracy "
|
||||
"within a global government. Start with a high-stakes meeting "
|
||||
"that sets the plot in motion."
|
||||
),
|
||||
icon="/public/thriller.svg",
|
||||
),
|
||||
cl.Starter(
|
||||
label="Develop a new board game",
|
||||
message=(
|
||||
"Develop a new, innovative board game. Describe the game's "
|
||||
"objective, rules, and unique mechanics. Create a scenario to "
|
||||
"illustrate gameplay."
|
||||
),
|
||||
icon="/public/game.svg",
|
||||
),
|
||||
],
|
||||
),
|
||||
cl.ChatProfile(
|
||||
name="Manual",
|
||||
markdown_description="Manually define your agents and tasks using a YAML file.",
|
||||
),
|
||||
]
|
||||
|
||||
@cl.on_chat_start
|
||||
async def start_chat():
|
||||
try:
|
||||
model_name = load_setting("model_name") or os.getenv("MODEL_NAME", "gpt-4o-mini")
|
||||
cl.user_session.set("model_name", model_name)
|
||||
logger.debug(f"Model name: {model_name}")
|
||||
|
||||
cl.user_session.set(
|
||||
"message_history",
|
||||
[{"role": "system", "content": "You are a helpful assistant."}],
|
||||
)
|
||||
|
||||
if not os.path.exists("tools.py"):
|
||||
with open("tools.py", "w") as f:
|
||||
f.write("# Add your custom tools here\n")
|
||||
|
||||
if not os.path.exists("agents.yaml"):
|
||||
with open("agents.yaml", "w") as f:
|
||||
f.write("# Add your custom agents here\n")
|
||||
|
||||
settings = await cl.ChatSettings(
|
||||
[
|
||||
TextInput(id="Model", label="OpenAI - Model", initial=model_name),
|
||||
TextInput(id="BaseUrl", label="OpenAI - Base URL", initial=config_list[0]['base_url']),
|
||||
TextInput(id="ApiKey", label="OpenAI - API Key", initial=config_list[0]['api_key']),
|
||||
Select(
|
||||
id="Framework",
|
||||
label="Framework",
|
||||
values=["praisonai", "crewai", "autogen"],
|
||||
initial_index=0,
|
||||
),
|
||||
]
|
||||
).send()
|
||||
cl.user_session.set("settings", settings)
|
||||
chat_profile = cl.user_session.get("chat_profile")
|
||||
|
||||
if chat_profile == "Manual":
|
||||
agent_file = "agents.yaml"
|
||||
full_agent_file_path = os.path.abspath(agent_file)
|
||||
if os.path.exists(full_agent_file_path):
|
||||
with open(full_agent_file_path, 'r') as f:
|
||||
yaml_content = f.read()
|
||||
msg = cl.Message(content=yaml_content, language="yaml")
|
||||
await msg.send()
|
||||
|
||||
full_tools_file_path = os.path.abspath("tools.py")
|
||||
if os.path.exists(full_tools_file_path):
|
||||
with open(full_tools_file_path, 'r') as f:
|
||||
tools_content = f.read()
|
||||
msg = cl.Message(content=tools_content, language="python")
|
||||
await msg.send()
|
||||
|
||||
settings = await cl.ChatSettings(
|
||||
[
|
||||
TextInput(id="Model", label="OpenAI - Model", initial=model_name),
|
||||
TextInput(id="BaseUrl", label="OpenAI - Base URL", initial=config_list[0]['base_url']),
|
||||
TextInput(id="ApiKey", label="OpenAI - API Key", initial=config_list[0]['api_key']),
|
||||
Select(
|
||||
id="Framework",
|
||||
label="Framework",
|
||||
values=["praisonai", "crewai", "autogen"],
|
||||
initial_index=0,
|
||||
),
|
||||
TextInput(id="agents", label="agents.yaml", initial=yaml_content, multiline=True),
|
||||
TextInput(id="tools", label="tools.py", initial=tools_content, multiline=True),
|
||||
]
|
||||
).send()
|
||||
cl.user_session.set("settings", settings)
|
||||
|
||||
res = await cl.AskActionMessage(
|
||||
content="Pick an action!",
|
||||
actions=actions,
|
||||
).send()
|
||||
if res and res.get("value") == "modify":
|
||||
await cl.Message(content="Modify the agents and tools from below settings", actions=actions).send()
|
||||
elif res and res.get("value") == "run":
|
||||
await main(cl.Message(content="", actions=actions))
|
||||
|
||||
await on_settings_update(settings)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in start_chat: {str(e)}")
|
||||
await cl.Message(content=f"An error occurred while starting the chat: {str(e)}").send()
|
||||
|
||||
@cl.on_chat_resume
|
||||
async def on_chat_resume(thread: ThreadDict):
|
||||
try:
|
||||
message_history = cl.user_session.get("message_history", [])
|
||||
root_messages = [m for m in thread["steps"] if m["parentId"] is None]
|
||||
for message in root_messages:
|
||||
if message["type"] == "user_message":
|
||||
message_history.append({"role": "user", "content": message["output"]})
|
||||
elif message["type"] == "ai_message":
|
||||
message_history.append({"role": "assistant", "content": message["content"]})
|
||||
cl.user_session.set("message_history", message_history)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in on_chat_resume: {str(e)}")
|
||||
|
||||
@cl.on_message
|
||||
async def main(message: cl.Message):
|
||||
try:
|
||||
logger.info(f"User message: {message.content}")
|
||||
msg = cl.Message(content="")
|
||||
await msg.stream_token(f"🔄 Processing your request: {message.content}...")
|
||||
|
||||
# Run PraisonAI
|
||||
result = await ui_run_praisonai(config, message.content, tools_dict)
|
||||
|
||||
message_history = cl.user_session.get("message_history", [])
|
||||
message_history.append({"role": "user", "content": message.content})
|
||||
message_history.append({"role": "assistant", "content": str(result)})
|
||||
cl.user_session.set("message_history", message_history)
|
||||
await msg.send()
|
||||
except Exception as e:
|
||||
error_msg = f"Error running PraisonAI agents: {str(e)}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
await cl.Message(content=error_msg, author="System").send()
|
||||
|
||||
@cl.on_settings_update
|
||||
async def on_settings_update(settings):
|
||||
try:
|
||||
global config_list, framework
|
||||
config_list[0]['model'] = settings["Model"]
|
||||
config_list[0]['base_url'] = settings["BaseUrl"]
|
||||
config_list[0]['api_key'] = settings["ApiKey"]
|
||||
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
await save_setting_with_retry("model_name", config_list[0]['model'])
|
||||
await save_setting_with_retry("base_url", config_list[0]['base_url'])
|
||||
await save_setting_with_retry("api_key", config_list[0]['api_key'])
|
||||
break
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e) and attempt < MAX_RETRIES - 1:
|
||||
await asyncio.sleep(RETRY_DELAY)
|
||||
continue
|
||||
raise
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = config_list[0]['api_key']
|
||||
os.environ["OPENAI_MODEL_NAME"] = config_list[0]['model']
|
||||
os.environ["OPENAI_API_BASE"] = config_list[0]['base_url']
|
||||
os.environ["MODEL_NAME"] = config_list[0]['model']
|
||||
framework = settings["Framework"]
|
||||
os.environ["FRAMEWORK"] = framework
|
||||
|
||||
if "agents" in settings:
|
||||
with open("agents.yaml", "w") as f:
|
||||
f.write(settings["agents"])
|
||||
if "tools" in settings:
|
||||
with open("tools.py", "w") as f:
|
||||
f.write(settings["tools"])
|
||||
|
||||
thread_id = cl.user_session.get("thread_id")
|
||||
if thread_id:
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
thread = await cl_data.get_thread(thread_id)
|
||||
if thread:
|
||||
metadata = thread.get("metadata", {})
|
||||
if isinstance(metadata, str):
|
||||
try:
|
||||
import json
|
||||
metadata = json.loads(metadata)
|
||||
except json.JSONDecodeError:
|
||||
metadata = {}
|
||||
metadata["model_name"] = config_list[0]['model']
|
||||
await cl_data.update_thread(thread_id, metadata=metadata)
|
||||
cl.user_session.set("metadata", metadata)
|
||||
break
|
||||
except sqlite3.OperationalError as e:
|
||||
if "database is locked" in str(e) and attempt < MAX_RETRIES - 1:
|
||||
await asyncio.sleep(RETRY_DELAY)
|
||||
continue
|
||||
raise
|
||||
|
||||
logger.info("Settings updated successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating settings: {str(e)}")
|
||||
await cl.Message(content=f"An error occurred while updating settings: {str(e)}. Retrying...").send()
|
||||
try:
|
||||
await asyncio.sleep(RETRY_DELAY * 2)
|
||||
await on_settings_update(settings)
|
||||
except Exception as e:
|
||||
logger.error(f"Final retry failed: {str(e)}")
|
||||
await cl.Message(content=f"Failed to update settings after retries: {str(e)}").send()
|
||||
@@ -0,0 +1,57 @@
|
||||
import logging
|
||||
from typing import Dict, Any, Callable, Optional, Union
|
||||
import asyncio
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class CallbackManager:
|
||||
"""Manages callbacks for the PraisonAI UI"""
|
||||
|
||||
def __init__(self):
|
||||
self._callbacks: Dict[str, Dict[str, Union[Callable, bool]]] = {}
|
||||
|
||||
def register(self, name: str, callback: Callable, is_async: bool = False) -> None:
|
||||
"""Register a callback function"""
|
||||
self._callbacks[name] = {
|
||||
'func': callback,
|
||||
'is_async': is_async
|
||||
}
|
||||
|
||||
async def call(self, name: str, **kwargs) -> None:
|
||||
"""Call a registered callback"""
|
||||
if name not in self._callbacks:
|
||||
logger.warning(f"No callback registered for {name}")
|
||||
return
|
||||
|
||||
callback_info = self._callbacks[name]
|
||||
func = callback_info['func']
|
||||
is_async = callback_info['is_async']
|
||||
|
||||
try:
|
||||
if is_async:
|
||||
await func(**kwargs)
|
||||
else:
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
await func(**kwargs)
|
||||
else:
|
||||
await asyncio.get_event_loop().run_in_executor(None, lambda: func(**kwargs))
|
||||
except Exception as e:
|
||||
logger.error(f"Error in callback {name}: {str(e)}")
|
||||
|
||||
# Global callback manager instance
|
||||
callback_manager = CallbackManager()
|
||||
|
||||
def register_callback(name: str, callback: Callable, is_async: bool = False) -> None:
|
||||
"""Register a callback with the global callback manager"""
|
||||
callback_manager.register(name, callback, is_async)
|
||||
|
||||
async def trigger_callback(name: str, **kwargs) -> None:
|
||||
"""Trigger a callback from the global callback manager"""
|
||||
await callback_manager.call(name, **kwargs)
|
||||
|
||||
# Decorator for registering callbacks
|
||||
def callback(name: str, is_async: bool = False):
|
||||
def decorator(func):
|
||||
register_callback(name, func, is_async)
|
||||
return func
|
||||
return decorator
|
||||
@@ -0,0 +1,474 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import os
|
||||
import importlib
|
||||
import inspect
|
||||
import yaml
|
||||
import logging
|
||||
from .callbacks import trigger_callback
|
||||
import asyncio
|
||||
import chainlit as cl
|
||||
from queue import Queue
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
agent_file = "agents.yaml"
|
||||
|
||||
with open(agent_file, 'r') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
topic = "get from the message content from the chainlit user message"
|
||||
|
||||
# Create a message queue
|
||||
message_queue = Queue()
|
||||
|
||||
async def process_message_queue():
|
||||
"""Process messages in the queue and send them to Chainlit"""
|
||||
while True:
|
||||
try:
|
||||
if not message_queue.empty():
|
||||
msg_data = message_queue.get()
|
||||
await cl.Message(**msg_data).send()
|
||||
await asyncio.sleep(0.1) # Small delay to prevent busy waiting
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing message queue: {e}")
|
||||
|
||||
def load_tools_from_tools_py():
|
||||
"""
|
||||
Imports and returns all contents from tools.py file.
|
||||
Also adds the tools to the global namespace.
|
||||
|
||||
Returns:
|
||||
list: A list of callable functions with proper formatting
|
||||
"""
|
||||
tools_list = []
|
||||
try:
|
||||
# Try to import tools.py from current directory
|
||||
spec = importlib.util.spec_from_file_location("tools", "tools.py")
|
||||
logger.info(f"Spec: {spec}")
|
||||
if spec is None:
|
||||
logger.info("tools.py not found in current directory")
|
||||
return tools_list
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
# Get all module attributes except private ones and classes
|
||||
for name, obj in inspect.getmembers(module):
|
||||
if (not name.startswith('_') and
|
||||
callable(obj) and
|
||||
not inspect.isclass(obj)):
|
||||
# Add the function to global namespace
|
||||
globals()[name] = obj
|
||||
# Format the tool as an OpenAI function
|
||||
tool = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": name,
|
||||
"description": obj.__doc__ or f"Function to {name.replace('_', ' ')}",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {
|
||||
"type": "string",
|
||||
"description": "The search query to look up information about"
|
||||
}
|
||||
},
|
||||
"required": ["query"]
|
||||
}
|
||||
}
|
||||
}
|
||||
# Add formatted tool to tools list
|
||||
tools_list.append(tool)
|
||||
logger.info(f"Loaded and globalized tool function: {name}")
|
||||
|
||||
logger.info(f"Loaded {len(tools_list)} tool functions from tools.py")
|
||||
logger.info(f"Tools list: {tools_list}")
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Error loading tools from tools.py: {e}")
|
||||
|
||||
return tools_list
|
||||
|
||||
async def step_callback(step_details):
|
||||
"""Callback for agent steps"""
|
||||
logger.info(f"[CALLBACK DEBUG] Step callback triggered with details: {step_details}")
|
||||
try:
|
||||
# Queue message for agent response
|
||||
if step_details.get("response"):
|
||||
message_queue.put({
|
||||
"content": f"Agent Response: {step_details.get('response')}",
|
||||
"author": step_details.get("agent_name", "Agent")
|
||||
})
|
||||
logger.info("[CALLBACK DEBUG] Queued agent response message")
|
||||
|
||||
# Queue message for tool usage
|
||||
if step_details.get("tool_name"):
|
||||
message_queue.put({
|
||||
"content": f"🛠️ Using tool: {step_details.get('tool_name')}",
|
||||
"author": "System"
|
||||
})
|
||||
logger.info("[CALLBACK DEBUG] Queued tool usage message")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in step callback: {str(e)}", exc_info=True)
|
||||
|
||||
async def task_callback(task_output):
|
||||
"""Callback for task completion"""
|
||||
logger.info(f"[CALLBACK DEBUG] Task callback triggered with output: {task_output}")
|
||||
try:
|
||||
# Create message content
|
||||
if hasattr(task_output, 'raw'):
|
||||
content = task_output.raw
|
||||
elif hasattr(task_output, 'content'):
|
||||
content = task_output.content
|
||||
else:
|
||||
content = str(task_output)
|
||||
|
||||
# Queue the message
|
||||
message_queue.put({
|
||||
"content": f"Task Output: {content}",
|
||||
"author": "Task"
|
||||
})
|
||||
logger.info("[CALLBACK DEBUG] Queued task completion message")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in task callback: {str(e)}", exc_info=True)
|
||||
|
||||
async def step_callback_wrapper(step_details):
|
||||
logger.info(f"[CALLBACK DEBUG] Step callback wrapper triggered with details: {step_details}")
|
||||
try:
|
||||
# Check if we have a Chainlit context
|
||||
if not cl.context.context_var.get():
|
||||
logger.warning("[CALLBACK DEBUG] No Chainlit context available in wrapper")
|
||||
return
|
||||
logger.info("[CALLBACK DEBUG] Chainlit context found in wrapper")
|
||||
|
||||
# Create a message for the agent's response
|
||||
if step_details.get("response"):
|
||||
logger.info(f"[CALLBACK DEBUG] Sending agent response from wrapper: {step_details.get('response')}")
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"{role_name}: {step_details.get('response')}",
|
||||
author=role_name,
|
||||
).send()
|
||||
logger.info("[CALLBACK DEBUG] Successfully sent agent response message from wrapper")
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending agent response message from wrapper: {str(e)}")
|
||||
|
||||
# Create a message for any tool usage
|
||||
if step_details.get("tool_name"):
|
||||
logger.info(f"[CALLBACK DEBUG] Sending tool usage from wrapper: {step_details.get('tool_name')}")
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"🛠️ {role_name} is using tool: {step_details.get('tool_name')}",
|
||||
author="System",
|
||||
).send()
|
||||
logger.info("[CALLBACK DEBUG] Successfully sent tool usage message from wrapper")
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending tool usage message from wrapper: {str(e)}")
|
||||
|
||||
# Create a message for any thoughts or reasoning
|
||||
if step_details.get("thought"):
|
||||
logger.info(f"[CALLBACK DEBUG] Sending thought from wrapper: {step_details.get('thought')}")
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"💭 {role_name}'s thought: {step_details.get('thought')}",
|
||||
author=role_name,
|
||||
).send()
|
||||
logger.info("[CALLBACK DEBUG] Successfully sent thought message from wrapper")
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending thought message from wrapper: {str(e)}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in step callback wrapper: {str(e)}", exc_info=True)
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"Error in step callback: {str(e)}",
|
||||
author="System",
|
||||
).send()
|
||||
except Exception as send_error:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending error message: {str(send_error)}")
|
||||
|
||||
async def task_callback_wrapper(task_output):
|
||||
logger.info(f"[CALLBACK DEBUG] Task callback wrapper triggered with output type: {type(task_output)}")
|
||||
try:
|
||||
# Check if we have a Chainlit context
|
||||
if not cl.context.context_var.get():
|
||||
logger.warning("[CALLBACK DEBUG] No Chainlit context available in task wrapper")
|
||||
return
|
||||
logger.info("[CALLBACK DEBUG] Chainlit context found in task wrapper")
|
||||
|
||||
# Create a message for task completion
|
||||
if hasattr(task_output, 'raw'):
|
||||
content = task_output.raw
|
||||
logger.info("[CALLBACK DEBUG] Using raw output")
|
||||
elif hasattr(task_output, 'content'):
|
||||
content = task_output.content
|
||||
logger.info("[CALLBACK DEBUG] Using content output")
|
||||
else:
|
||||
content = str(task_output)
|
||||
logger.info("[CALLBACK DEBUG] Using string representation of output")
|
||||
|
||||
logger.info(f"[CALLBACK DEBUG] Sending task completion message from wrapper: {content[:100]}...")
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"✅ {role_name} completed task:\n{content}",
|
||||
author=role_name,
|
||||
).send()
|
||||
logger.info("[CALLBACK DEBUG] Successfully sent task completion message from wrapper")
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending task completion message from wrapper: {str(e)}")
|
||||
|
||||
# If there are any additional task details
|
||||
if hasattr(task_output, 'details'):
|
||||
logger.info("[CALLBACK DEBUG] Task has additional details")
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"📝 Additional details:\n{task_output.details}",
|
||||
author=role_name,
|
||||
).send()
|
||||
logger.info("[CALLBACK DEBUG] Successfully sent additional details message")
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending additional details message: {str(e)}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in task callback wrapper: {str(e)}", exc_info=True)
|
||||
try:
|
||||
await cl.Message(
|
||||
content=f"Error in task callback: {str(e)}",
|
||||
author="System",
|
||||
).send()
|
||||
except Exception as send_error:
|
||||
logger.error(f"[CALLBACK DEBUG] Error sending error message: {str(send_error)}")
|
||||
|
||||
def sync_task_callback_wrapper(task_output):
|
||||
logger.info("[CALLBACK DEBUG] Sync task callback wrapper triggered")
|
||||
try:
|
||||
# Create a new event loop for this thread if there isn't one
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
logger.info("[CALLBACK DEBUG] Got existing event loop")
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
logger.info("[CALLBACK DEBUG] Created new event loop")
|
||||
|
||||
if loop.is_running():
|
||||
# If loop is running, schedule the callback
|
||||
logger.info("[CALLBACK DEBUG] Loop is running, scheduling callback")
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
task_callback_wrapper(task_output),
|
||||
loop
|
||||
)
|
||||
else:
|
||||
# If loop is not running, run it directly
|
||||
logger.info("[CALLBACK DEBUG] Loop is not running, running callback directly")
|
||||
loop.run_until_complete(task_callback_wrapper(task_output))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in sync task callback: {str(e)}", exc_info=True)
|
||||
|
||||
def sync_step_callback_wrapper(step_details):
|
||||
logger.info("[CALLBACK DEBUG] Sync step callback wrapper triggered")
|
||||
try:
|
||||
# Create a new event loop for this thread if there isn't one
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
logger.info("[CALLBACK DEBUG] Got existing event loop")
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
logger.info("[CALLBACK DEBUG] Created new event loop")
|
||||
|
||||
if loop.is_running():
|
||||
# If loop is running, schedule the callback
|
||||
logger.info("[CALLBACK DEBUG] Loop is running, scheduling callback")
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
step_callback_wrapper(step_details),
|
||||
loop
|
||||
)
|
||||
else:
|
||||
# If loop is not running, run it directly
|
||||
logger.info("[CALLBACK DEBUG] Loop is not running, running callback directly")
|
||||
loop.run_until_complete(step_callback_wrapper(step_details))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in sync step callback: {str(e)}", exc_info=True)
|
||||
|
||||
async def ui_run_praisonai(config, topic, tools_dict):
|
||||
"""Run PraisonAI with the given configuration and topic."""
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
agents = {}
|
||||
tasks = []
|
||||
tasks_dict = {}
|
||||
|
||||
try:
|
||||
# Start message queue processor
|
||||
queue_processor = asyncio.create_task(process_message_queue())
|
||||
|
||||
# Create agents for each role
|
||||
for role, details in config['roles'].items():
|
||||
# Format the role name and other details
|
||||
role_name = details.get('name', role).format(topic=topic)
|
||||
role_filled = details.get('role', role).format(topic=topic)
|
||||
goal_filled = details['goal'].format(topic=topic)
|
||||
backstory_filled = details['backstory'].format(topic=topic)
|
||||
|
||||
# Test message to verify Chainlit is working
|
||||
await cl.Message(
|
||||
content=f"[DEBUG] Creating agent: {role_name}",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
# Create a sync wrapper for the step callback
|
||||
def step_callback_sync(step_details):
|
||||
try:
|
||||
# Create a new event loop for this thread
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
# Add agent name to step details
|
||||
step_details["agent_name"] = role_name
|
||||
|
||||
# Run the callback
|
||||
loop.run_until_complete(step_callback(step_details))
|
||||
loop.close()
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in step callback: {str(e)}", exc_info=True)
|
||||
|
||||
agent = Agent(
|
||||
name=role_name,
|
||||
role=role_filled,
|
||||
goal=goal_filled,
|
||||
backstory=backstory_filled,
|
||||
llm=details.get('llm', 'gpt-4o'),
|
||||
verbose=True,
|
||||
allow_delegation=details.get('allow_delegation', False),
|
||||
max_iter=details.get('max_iter', 15),
|
||||
max_rpm=details.get('max_rpm'),
|
||||
max_execution_time=details.get('max_execution_time'),
|
||||
cache=details.get('cache', True),
|
||||
step_callback=step_callback_sync
|
||||
)
|
||||
agents[role] = agent
|
||||
|
||||
# Create tasks for each role
|
||||
for role, details in config['roles'].items():
|
||||
agent = agents[role]
|
||||
tools_list = []
|
||||
|
||||
# Get tools for this role
|
||||
for tool_name in details.get('tools', []):
|
||||
if tool_name in tools_dict:
|
||||
tool_func = tools_dict[tool_name]
|
||||
tools_list.append(tool_func)
|
||||
|
||||
# Create tasks for the agent
|
||||
for task_name, task_details in details.get('tasks', {}).items():
|
||||
description_filled = task_details['description'].format(topic=topic)
|
||||
expected_output_filled = task_details['expected_output'].format(topic=topic)
|
||||
|
||||
# Test message to verify task creation
|
||||
await cl.Message(
|
||||
content=f"[DEBUG] Created task: {task_name} for agent {role_name}",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
# Create a sync wrapper for the task callback
|
||||
def task_callback_sync(task_output):
|
||||
try:
|
||||
# Create a new event loop for this thread
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
# Run the callback
|
||||
loop.run_until_complete(task_callback(task_output))
|
||||
loop.close()
|
||||
except Exception as e:
|
||||
logger.error(f"[CALLBACK DEBUG] Error in task callback: {str(e)}", exc_info=True)
|
||||
|
||||
task = Task(
|
||||
description=description_filled,
|
||||
expected_output=expected_output_filled,
|
||||
agent=agent,
|
||||
tools=tools_list,
|
||||
async_execution=True,
|
||||
context=[],
|
||||
config=task_details.get('config', {}),
|
||||
output_json=task_details.get('output_json'),
|
||||
output_pydantic=task_details.get('output_pydantic'),
|
||||
output_file=task_details.get('output_file', ""),
|
||||
callback=task_callback_sync,
|
||||
create_directory=task_details.get('create_directory', False)
|
||||
)
|
||||
|
||||
tasks.append(task)
|
||||
tasks_dict[task_name] = task
|
||||
|
||||
# Set up task contexts
|
||||
for role, details in config['roles'].items():
|
||||
for task_name, task_details in details.get('tasks', {}).items():
|
||||
task = tasks_dict[task_name]
|
||||
context_tasks = [tasks_dict[ctx] for ctx in task_details.get('context', [])
|
||||
if ctx in tasks_dict]
|
||||
task.context = context_tasks
|
||||
|
||||
# Send the start message
|
||||
await cl.Message(
|
||||
content="Starting PraisonAI agents execution...",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
# Create and run the PraisonAI agents
|
||||
if config.get('process') == 'hierarchical':
|
||||
crew = PraisonAIAgents(
|
||||
agents=list(agents.values()),
|
||||
tasks=tasks,
|
||||
verbose=True,
|
||||
process="hierarchical",
|
||||
manager_llm=config.get('manager_llm', 'gpt-4o')
|
||||
)
|
||||
else:
|
||||
crew = PraisonAIAgents(
|
||||
agents=list(agents.values()),
|
||||
tasks=tasks,
|
||||
verbose=2
|
||||
)
|
||||
|
||||
# Store the crew in the user session
|
||||
cl.user_session.set("crew", crew)
|
||||
|
||||
# Run the agents in a separate thread
|
||||
loop = asyncio.get_event_loop()
|
||||
response = await loop.run_in_executor(None, crew.start)
|
||||
|
||||
logger.debug(f"[CALLBACK DEBUG] Result: {response}")
|
||||
|
||||
# Convert response to string if it's not already
|
||||
if hasattr(response, 'raw'):
|
||||
result = response.raw
|
||||
elif hasattr(response, 'content'):
|
||||
result = response.content
|
||||
else:
|
||||
result = str(response)
|
||||
|
||||
# Send the completion message
|
||||
await cl.Message(
|
||||
content="PraisonAI agents execution completed.",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
# After getting the response, wait a bit for remaining messages
|
||||
await asyncio.sleep(1) # Give time for final messages to be processed
|
||||
queue_processor.cancel() # Stop the queue processor
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error in ui_run_praisonai: {str(e)}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
await cl.Message(
|
||||
content=error_msg,
|
||||
author="System"
|
||||
).send()
|
||||
raise
|
||||
@@ -0,0 +1,81 @@
|
||||
import os
|
||||
import logging
|
||||
from dotenv import load_dotenv
|
||||
import chainlit as cl
|
||||
from chainlit.types import ThreadDict
|
||||
import yaml
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# Add the parent directory to sys.path to allow imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||||
|
||||
from praisonai.ui.colab import ui_run_praisonai, load_tools_from_tools_py
|
||||
from praisonai.ui.callbacks import callback, trigger_callback
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger(__name__)
|
||||
log_level = os.getenv("LOGLEVEL", "INFO").upper()
|
||||
logger.setLevel(log_level)
|
||||
|
||||
# Load agent configuration
|
||||
agent_file = "agents.yaml"
|
||||
with open(agent_file, 'r') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# Load tools
|
||||
tools_dict = load_tools_from_tools_py()
|
||||
|
||||
@cl.on_message
|
||||
async def main(message: cl.Message):
|
||||
"""Main message handler for Chainlit"""
|
||||
try:
|
||||
logger.info(f"Processing message: {message.content}")
|
||||
await cl.Message(
|
||||
content=f"🔄 Processing your request about: {message.content}...",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
await cl.Message(
|
||||
content="Using Running PraisonAI Agents...",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
# Run PraisonAI with the message content as the topic
|
||||
result = await ui_run_praisonai(config, message.content, tools_dict)
|
||||
|
||||
# Send the final result
|
||||
await cl.Message(
|
||||
content=result,
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error running PraisonAI agents: {str(e)}"
|
||||
logger.error(error_msg, exc_info=True)
|
||||
await cl.Message(
|
||||
content=error_msg,
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
@cl.on_chat_start
|
||||
async def start():
|
||||
"""Handler for chat start"""
|
||||
await cl.Message(
|
||||
content="👋 Welcome! I'm your AI assistant. What would you like to work on?",
|
||||
author="System"
|
||||
).send()
|
||||
|
||||
# Authentication setup (optional)
|
||||
if os.getenv("CHAINLIT_AUTH_SECRET"):
|
||||
@cl.password_auth_callback
|
||||
def auth_callback(username: str, password: str) -> cl.User:
|
||||
# Replace with your authentication logic
|
||||
if username == os.getenv("CHAINLIT_USERNAME", "admin") and \
|
||||
password == os.getenv("CHAINLIT_PASSWORD", "admin"):
|
||||
return cl.User(identifier=username, metadata={"role": "user"})
|
||||
return None
|
||||
@@ -1 +1 @@
|
||||
# Welcome to Praison AI! 🚀🤖
|
||||
# Welcome to PraisonAI! 🚀
|
||||
@@ -0,0 +1,133 @@
|
||||
# Understanding Tool Integration in AI Agents - A Beginner's Guide
|
||||
|
||||
## Overview
|
||||
This guide explains how to properly integrate tools (functions) that an AI agent can use, making them both understandable to the OpenAI API and executable by your code.
|
||||
|
||||
## Key Components
|
||||
|
||||
### 1. Tool Definition Structure
|
||||
```python
|
||||
# Example tool definition in tools.py
|
||||
def search_tool(query: str) -> list:
|
||||
"""
|
||||
Perform a web search using DuckDuckGo.
|
||||
|
||||
Args:
|
||||
query (str): The search query string.
|
||||
|
||||
Returns:
|
||||
list: Search results with title, url, and snippet.
|
||||
"""
|
||||
# Function implementation...
|
||||
```
|
||||
|
||||
### 2. Tool Dictionary Format
|
||||
```python
|
||||
tools_dict = {
|
||||
'search_tool': {
|
||||
'type': 'function',
|
||||
'function': {
|
||||
'name': 'search_tool',
|
||||
'description': '...',
|
||||
'parameters': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'query': {'type': 'string'}
|
||||
}
|
||||
}
|
||||
},
|
||||
'callable': search_tool # The actual Python function
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## The Two-Part System
|
||||
|
||||
### Part 1: OpenAI API Communication
|
||||
```python
|
||||
# task_tools: What OpenAI understands
|
||||
task_tools = []
|
||||
tool_def = tools_dict[tool_name].copy()
|
||||
callable_func = tool_def.pop("callable") # Remove the Python function
|
||||
task_tools.append(tool_def) # Add clean JSON-serializable definition
|
||||
```
|
||||
|
||||
### Part 2: Function Execution
|
||||
```python
|
||||
# role_tools: What your code executes
|
||||
role_tools = []
|
||||
role_tools.append(callable_func) # Store the actual function
|
||||
agent.tools = role_tools # Give agent access to executable functions
|
||||
```
|
||||
|
||||
## Putting It All Together
|
||||
|
||||
```python
|
||||
# Initialize empty lists
|
||||
role_tools = [] # For executable functions
|
||||
task_tools = [] # For OpenAI API definitions
|
||||
|
||||
# Process each tool
|
||||
for tool_name in tools_list:
|
||||
if tool_name in tools_dict:
|
||||
# 1. Get the tool definition
|
||||
tool_def = tools_dict[tool_name].copy()
|
||||
|
||||
# 2. Separate the callable function
|
||||
callable_func = tool_def.pop("callable")
|
||||
|
||||
# 3. Store the function for execution
|
||||
role_tools.append(callable_func)
|
||||
|
||||
# 4. Store the API definition
|
||||
task_tools.append(tool_def)
|
||||
|
||||
# 5. Give agent access to functions
|
||||
agent.tools = role_tools
|
||||
|
||||
# Create task with API definitions
|
||||
task = Task(
|
||||
description="...",
|
||||
tools=task_tools, # OpenAI API will use these
|
||||
agent=agent, # Agent has access to callable functions
|
||||
# ... other parameters ...
|
||||
)
|
||||
```
|
||||
|
||||
## Why This Works
|
||||
|
||||
1. **API Communication**
|
||||
- OpenAI API receives clean JSON tool definitions
|
||||
- No Python functions that would cause serialization errors
|
||||
|
||||
2. **Function Execution**
|
||||
- Agent has access to actual Python functions
|
||||
- Can execute tools when OpenAI decides to use them
|
||||
|
||||
3. **Separation of Concerns**
|
||||
- `task_tools`: Describes what tools can do (for OpenAI)
|
||||
- `role_tools`: Actually does the work (for Python)
|
||||
|
||||
## Common Errors and Solutions
|
||||
|
||||
1. **"Invalid type for 'tools[0]'"**
|
||||
- Cause: Sending null or invalid tool definition to OpenAI
|
||||
- Solution: Use proper tool definition format in `task_tools`
|
||||
|
||||
2. **"Object of type function is not JSON serializable"**
|
||||
- Cause: Trying to send Python function to OpenAI API
|
||||
- Solution: Remove callable function from API definition
|
||||
|
||||
3. **"Tool is not callable"**
|
||||
- Cause: Agent doesn't have access to executable functions
|
||||
- Solution: Set `agent.tools = role_tools`
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Always initialize both `task_tools` and `role_tools` lists
|
||||
2. Make clean copies of tool definitions to avoid modifying originals
|
||||
3. Keep tool definitions JSON-serializable for API communication
|
||||
4. Ensure agents have access to callable functions
|
||||
5. Document tool parameters and return values clearly
|
||||
|
||||
This structure maintains clean separation between API communication and actual function execution, making your AI agent system both reliable and maintainable.
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.20"
|
||||
version = "2.0.32"
|
||||
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,14 +12,20 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.0.16",
|
||||
"praisonaiagents>=0.0.23",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
ui = ["chainlit==2.0rc1"]
|
||||
ui = [
|
||||
"chainlit==1.3.2",
|
||||
"sqlalchemy>=2.0.36",
|
||||
"aiosqlite>=0.20.0",
|
||||
"greenlet>=3.0.3",
|
||||
"pydantic<=2.10.1"
|
||||
]
|
||||
gradio = ["gradio>=4.26.0"]
|
||||
api = ["flask>=3.0.0"]
|
||||
agentops = ["agentops>=0.3.12"]
|
||||
@@ -28,7 +34,7 @@ openai = ["langchain-openai>=0.1.7"]
|
||||
anthropic = ["langchain-anthropic>=0.1.13"]
|
||||
cohere = ["langchain-cohere>=0.1.4"]
|
||||
chat = [
|
||||
"chainlit==2.0rc1",
|
||||
"chainlit==1.3.2",
|
||||
"litellm>=1.41.8",
|
||||
"aiosqlite>=0.20.0",
|
||||
"greenlet>=3.0.3",
|
||||
@@ -40,7 +46,7 @@ chat = [
|
||||
"pydantic<=2.10.1"
|
||||
]
|
||||
code = [
|
||||
"chainlit==2.0rc1",
|
||||
"chainlit==1.3.2",
|
||||
"litellm>=1.41.8",
|
||||
"aiosqlite>=0.20.0",
|
||||
"greenlet>=3.0.3",
|
||||
@@ -51,7 +57,7 @@ code = [
|
||||
"pydantic<=2.10.1"
|
||||
]
|
||||
realtime = [
|
||||
"chainlit==2.0rc1",
|
||||
"chainlit==1.3.2",
|
||||
"litellm>=1.41.8",
|
||||
"aiosqlite>=0.20.0",
|
||||
"greenlet>=3.0.3",
|
||||
@@ -78,7 +84,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.7", "crewai"]
|
||||
|
||||
[tool.poetry]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.20"
|
||||
version = "2.0.32"
|
||||
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 = ""
|
||||
@@ -96,7 +102,7 @@ python = ">=3.10,<3.13"
|
||||
rich = ">=13.7"
|
||||
markdown = ">=3.5"
|
||||
pyparsing = ">=3.0.0"
|
||||
praisonaiagents = ">=0.0.16"
|
||||
praisonaiagents = ">=0.0.23"
|
||||
python-dotenv = ">=0.19.0"
|
||||
instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
@@ -193,7 +199,13 @@ setup-conda-env = "setup.setup_conda_env:main"
|
||||
praisonai-call = "praisonai.api.call:main"
|
||||
|
||||
[tool.poetry.extras]
|
||||
ui = ["chainlit"]
|
||||
ui = [
|
||||
"chainlit",
|
||||
"aiosqlite",
|
||||
"greenlet",
|
||||
"sqlalchemy",
|
||||
"pydantic"
|
||||
]
|
||||
gradio = ["gradio"]
|
||||
api = ["flask"]
|
||||
agentops = ["agentops"]
|
||||
|
||||
@@ -7,10 +7,4 @@ PyYAML>=6.0
|
||||
praisonaiagents>=0.0.4
|
||||
duckduckgo_search
|
||||
praisonai_tools
|
||||
flask>=2.0.0
|
||||
flask-socketio>=5.3.0
|
||||
python-socketio>=5.7.0
|
||||
eventlet>=0.33.0
|
||||
numpy>=1.21.0
|
||||
sounddevice>=0.4.5
|
||||
PyAudio>=0.2.13
|
||||
flask>=2.0.0
|
||||
@@ -482,7 +482,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "chainlit"
|
||||
version = "2.0rc1"
|
||||
version = "1.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiofiles" },
|
||||
@@ -509,9 +509,9 @@ dependencies = [
|
||||
{ name = "uvicorn" },
|
||||
{ name = "watchfiles" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4d/e0/3bdf4dc3cd44bc60d7db1d1c78082d3a235260cd794180b2060766bcd880/chainlit-2.0rc1.tar.gz", hash = "sha256:7b4bd97f49ddddd198136c69be28236b1ee6863bb20af25ec26aa8e3b5e5e847", size = 4496562 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6a/57/8c3c354b3e82fae0791b58304634b356aeea8791dd0b6f817a8d8787cad6/chainlit-1.3.2.tar.gz", hash = "sha256:5562246ca42c858a42e86efdd5a46c27fd93481706f6fe47416109c47ac41b77", size = 4271845 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/05/5fa6e54aed8494544d09df57140f115fb666181f7ae742dd224cad8ec6b1/chainlit-2.0rc1-py3-none-any.whl", hash = "sha256:7901818c4c19eccf389faeb98d65d6ba3efbe105c78461d0c972885130018a92", size = 4551902 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/d8/2a0c00b2236c93f31df429642de6414c56510d39392101b1b102074520d0/chainlit-1.3.2-py3-none-any.whl", hash = "sha256:c0926e8b157a67aede511a8220307889d04e9458ff3f94176e004fe533662d74", size = 4332216 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3061,7 +3061,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonai"
|
||||
version = "2.0.20"
|
||||
version = "2.0.32"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "instructor" },
|
||||
@@ -3151,7 +3151,11 @@ realtime = [
|
||||
{ name = "yfinance" },
|
||||
]
|
||||
ui = [
|
||||
{ name = "aiosqlite" },
|
||||
{ name = "chainlit" },
|
||||
{ name = "greenlet" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "sqlalchemy" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
@@ -3160,10 +3164,11 @@ requires-dist = [
|
||||
{ name = "aiosqlite", marker = "extra == 'chat'", specifier = ">=0.20.0" },
|
||||
{ name = "aiosqlite", marker = "extra == 'code'", specifier = ">=0.20.0" },
|
||||
{ name = "aiosqlite", marker = "extra == 'realtime'", specifier = ">=0.20.0" },
|
||||
{ name = "chainlit", marker = "extra == 'chat'", specifier = "==2.0rc1" },
|
||||
{ name = "chainlit", marker = "extra == 'code'", specifier = "==2.0rc1" },
|
||||
{ name = "chainlit", marker = "extra == 'realtime'", specifier = "==2.0rc1" },
|
||||
{ name = "chainlit", marker = "extra == 'ui'", specifier = "==2.0rc1" },
|
||||
{ name = "aiosqlite", marker = "extra == 'ui'", specifier = ">=0.20.0" },
|
||||
{ name = "chainlit", marker = "extra == 'chat'", specifier = "==1.3.2" },
|
||||
{ name = "chainlit", marker = "extra == 'code'", specifier = "==1.3.2" },
|
||||
{ name = "chainlit", marker = "extra == 'realtime'", specifier = "==1.3.2" },
|
||||
{ name = "chainlit", marker = "extra == 'ui'", specifier = "==1.3.2" },
|
||||
{ name = "crawl4ai", marker = "extra == 'chat'", specifier = "==0.3.4" },
|
||||
{ name = "crawl4ai", marker = "extra == 'code'", specifier = "==0.3.4" },
|
||||
{ name = "crawl4ai", marker = "extra == 'realtime'", specifier = "==0.3.4" },
|
||||
@@ -3177,6 +3182,7 @@ requires-dist = [
|
||||
{ name = "greenlet", marker = "extra == 'chat'", specifier = ">=3.0.3" },
|
||||
{ name = "greenlet", marker = "extra == 'code'", specifier = ">=3.0.3" },
|
||||
{ name = "greenlet", marker = "extra == 'realtime'", specifier = ">=3.0.3" },
|
||||
{ name = "greenlet", marker = "extra == 'ui'", specifier = ">=3.0.3" },
|
||||
{ name = "instructor", specifier = ">=1.3.3" },
|
||||
{ name = "langchain-anthropic", marker = "extra == 'anthropic'", specifier = ">=0.1.13" },
|
||||
{ name = "langchain-cohere", marker = "extra == 'cohere'", specifier = ">=0.1.4" },
|
||||
@@ -3192,10 +3198,11 @@ 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.16" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.23" },
|
||||
{ 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" },
|
||||
{ name = "pydantic", marker = "extra == 'ui'", specifier = "<=2.10.1" },
|
||||
{ name = "pyngrok", marker = "extra == 'call'", specifier = ">=1.4.0" },
|
||||
{ name = "pyparsing", specifier = ">=3.0.0" },
|
||||
{ name = "python-dotenv", specifier = ">=0.19.0" },
|
||||
@@ -3206,6 +3213,7 @@ requires-dist = [
|
||||
{ name = "sqlalchemy", marker = "extra == 'chat'", specifier = ">=2.0.36" },
|
||||
{ name = "sqlalchemy", marker = "extra == 'code'", specifier = ">=2.0.36" },
|
||||
{ name = "sqlalchemy", marker = "extra == 'realtime'", specifier = ">=2.0.36" },
|
||||
{ name = "sqlalchemy", marker = "extra == 'ui'", specifier = ">=2.0.36" },
|
||||
{ name = "tavily-python", marker = "extra == 'chat'", specifier = "==0.5.0" },
|
||||
{ name = "tavily-python", marker = "extra == 'code'", specifier = "==0.5.0" },
|
||||
{ name = "tavily-python", marker = "extra == 'realtime'", specifier = "==0.5.0" },
|
||||
@@ -3243,16 +3251,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.16"
|
||||
version = "0.0.23"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "rich" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0b/43/aede54fe1f1570cb169029d186c1e09333c0080551ccd136b496d3a5c93b/praisonaiagents-0.0.16.tar.gz", hash = "sha256:867576b392f54d2a02ba49ab4e1f83818e4bd6979530dfc987ffebca9fce66db", size = 20789 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/87/08ff2ac7c365251fa07973fded3e68c2edc1173d8514e6fd90fc8ee7b131/praisonaiagents-0.0.23.tar.gz", hash = "sha256:1814d537b2625a5c7d4b61d07f5d5bd043f0ad8afc31fe9d4eb99a5ca54101bf", size = 25375 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/50/e0d73730f9899d78482748f711e6e05f138061d2d51650adaf964c258dc6/praisonaiagents-0.0.16-py3-none-any.whl", hash = "sha256:a1f4086a75383e842e477937580670334f8babe9d8e43aa809bfb7806888585f", size = 27323 },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/75/c3a1cf2adaf0811ab538029054fa993e82caffba2853546f41766b7e0aab/praisonaiagents-0.0.23-py3-none-any.whl", hash = "sha256:d6aaa406fc993ccd0a763aa426b7139c955e1cd99e6b204b06817ebc1a5855e3", size = 31734 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||