mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-08 01:08:39 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ed2d99a11 | ||
|
|
81307da7c8 | ||
|
|
fb75153b5c | ||
|
|
cddcfcf170 | ||
|
|
398b0473e0 | ||
|
|
c5d260782a | ||
|
|
116ac5a64d | ||
|
|
abf6e2e8d1 | ||
|
|
cb2b3617fa | ||
|
|
6de67c7d0d | ||
|
|
5699d90894 | ||
|
|
2982e8ea9c | ||
|
|
9dd2146342 | ||
|
|
f79184a6ee | ||
|
|
0985e12ad4 | ||
|
|
0fbb7972e1 | ||
|
|
5744ae853e | ||
|
|
bd6e3da4ff | ||
|
|
f2f51d9e8b | ||
|
|
4a1098603d | ||
|
|
5468e35bc1 | ||
|
|
b468267a87 | ||
|
|
48141bbd9e | ||
|
|
b3cdf53d07 | ||
|
|
aa594ddc32 | ||
|
|
5f330e8fb2 | ||
|
|
ff94e128de | ||
|
|
854a016fc5 | ||
|
|
12e8ed7b77 | ||
|
|
13c5f5537e | ||
|
|
e7c1614ac8 | ||
|
|
7cc6db2a34 | ||
|
|
b869bbc346 | ||
|
|
5492be4412 | ||
|
|
c2e33ef6a6 | ||
|
|
5b2e0a9417 | ||
|
|
2f6d9ebcc9 | ||
|
|
0610a5b3a4 | ||
|
|
7463744e62 | ||
|
|
c7428b8282 | ||
|
|
ff1deb6b97 | ||
|
|
bdbed2667d | ||
|
|
2810ec879c | ||
|
|
04a8c621bb | ||
|
|
17cbadaf64 | ||
|
|
fbcdf84350 | ||
|
|
ab3295caa1 | ||
|
|
95517f5007 | ||
|
|
3800825b38 | ||
|
|
f85e16ab87 | ||
|
|
dbdd3d3d9a | ||
|
|
1cc5dad01f | ||
|
|
3797e4fe25 | ||
|
|
d840e7d0ef | ||
|
|
6f9ca636aa | ||
|
|
f254d9e290 | ||
|
|
2e95279cd5 | ||
|
|
c218ad62ce | ||
|
|
d10849085d | ||
|
|
9594426fc2 | ||
|
|
1c6fc71a06 | ||
|
|
d7289acc1d | ||
|
|
54a748b4c7 | ||
|
|
9f62e9201a | ||
|
|
1b69360d9f | ||
|
|
9bdc6545ad | ||
|
|
06cd909367 | ||
|
|
67aeece7fc | ||
|
|
ef67d0753c | ||
|
|
f374f9f791 | ||
|
|
492fb29af9 | ||
|
|
cd56ebd5cf | ||
|
|
08e99f6ef7 | ||
|
|
670d653ae9 | ||
|
|
faa014b8b0 | ||
|
|
6d454d0c6e | ||
|
|
0ec3fe3510 | ||
|
|
707888cdf9 | ||
|
|
42051630bc | ||
|
|
bfcccb6355 | ||
|
|
e329afc394 | ||
|
|
9417cc6457 | ||
|
|
10a3d279ae | ||
|
|
2a916208e1 | ||
|
|
bcd0bbbd24 | ||
|
|
5701a40f11 | ||
|
|
3ffac395bb | ||
|
|
37119aa3ac | ||
|
|
8b2d324d3b | ||
|
|
6d0b29e60d | ||
|
|
583cbc5efa | ||
|
|
90dd84a152 | ||
|
|
ef7fa66e33 | ||
|
|
1659ed61bc | ||
|
|
b8939ef439 | ||
|
|
4bada9e5fc | ||
|
|
51c4cb00b0 | ||
|
|
ad96549ea3 | ||
|
|
183d10d7cc | ||
|
|
bce1559ab5 | ||
|
|
6f3fb87ba3 | ||
|
|
e7f6b2df67 | ||
|
|
08d72eeb80 | ||
|
|
11aefae90f | ||
|
|
10d5158d27 | ||
|
|
1d8b814fcd | ||
|
|
6e8a5b98a8 | ||
|
|
59d0ff8c95 | ||
|
|
b2109faa06 | ||
|
|
024eaed456 | ||
|
|
4fd3a572cf | ||
|
|
baaf8b6256 |
No files matched your search
+8
-1885
File diff suppressed because it is too large.
Load diff
@@ -20,7 +20,7 @@
|
||||
|
||||
</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.
|
||||
PraisonAI is a production-ready Multi-AI Agents framework with self-reflection, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. By integrating PraisonAI Agents, AutoGen, and CrewAI into a low-code solution, it streamlines the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration.
|
||||
|
||||
<div align="center">
|
||||
<a href="https://docs.praison.ai">
|
||||
@@ -37,35 +37,24 @@ PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application
|
||||
- 🧠 Reasoning AI Agents
|
||||
- 👁️ Multi Modal AI Agents
|
||||
- 🤝 Multi Agent Collaboration
|
||||
- ⚡ AI Agent Workflow
|
||||
- 🔄 Use CrewAI or AutoGen Framework
|
||||
- 🎭 AI Agent Workflow
|
||||
- 📚 Add Custom Knowledge
|
||||
- 🧠 Agents with Short and Long Term Memory
|
||||
- 📄 Chat with PDF Agents
|
||||
- 💻 Code Interpreter Agents
|
||||
- 📚 RAG Agents
|
||||
- 🤔 Async & Parallel Processing
|
||||
- 🔄 Auto Agents
|
||||
- 🔢 Math Agents
|
||||
- 🎯 Structured Output Agents
|
||||
- 🔗 LangChain Integrated Agents
|
||||
- 📞 Callback Agents
|
||||
- 🤏 Mini AI Agents
|
||||
- 🛠️ 100+ Custom Tools
|
||||
- 📄 YAML Configuration
|
||||
- 💯 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
|
||||
## Using Python Code
|
||||
|
||||
Light weight package dedicated for coding:
|
||||
```bash
|
||||
@@ -76,58 +65,13 @@ pip install praisonaiagents
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
### 1. Single Agent
|
||||
|
||||
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()
|
||||
from praisonaiagents import Agent
|
||||
agent = Agent(instructions="Your are a helpful AI assistant")
|
||||
agent.start("Write a movie script about a robot in Mars")
|
||||
```
|
||||
|
||||
Run:
|
||||
@@ -135,6 +79,396 @@ Run:
|
||||
python app.py
|
||||
```
|
||||
|
||||
### 2. Multi Agents
|
||||
|
||||
Create app.py file and add the code below:
|
||||
```python
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
|
||||
research_agent = Agent(instructions="Research about AI")
|
||||
summarise_agent = Agent(instructions="Summarise research agent's findings")
|
||||
agents = PraisonAIAgents(agents=[research_agent, summarise_agent])
|
||||
agents.start()
|
||||
```
|
||||
|
||||
Run:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
## Using No Code
|
||||
|
||||
### Auto Mode:
|
||||
```bash
|
||||
pip install praisonai
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
praisonai --auto create a movie script about Robots in Mars
|
||||
```
|
||||
|
||||
## Using JavaScript Code
|
||||
|
||||
```bash
|
||||
npm install praisonai
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
```javascript
|
||||
const { Agent } = require('praisonai');
|
||||
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
|
||||
agent.start('Write a movie script about a robot in Mars');
|
||||
```
|
||||
|
||||

|
||||
|
||||
## AI Agents Flow
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[ ]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
end
|
||||
|
||||
subgraph Agent2[ ]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
end
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Start,Output,Task1,Task2 input
|
||||
class Process,AgentIcon1,AgentIcon2 process
|
||||
class Tools1,Tools2 tools
|
||||
class Agent1,Agent2 transparent
|
||||
```
|
||||
|
||||
## AI Agents with Tools
|
||||
|
||||
Create AI agents that can use tools to interact with external systems and perform actions.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Tools
|
||||
direction TB
|
||||
T3[Internet Search]
|
||||
T1[Code Execution]
|
||||
T2[Formatting]
|
||||
end
|
||||
|
||||
Input[Input] ---> Agents
|
||||
subgraph Agents
|
||||
direction LR
|
||||
A1[Agent 1]
|
||||
A2[Agent 2]
|
||||
A3[Agent 3]
|
||||
end
|
||||
Agents ---> Output[Output]
|
||||
|
||||
T3 --> A1
|
||||
T1 --> A2
|
||||
T2 --> A3
|
||||
|
||||
style Tools fill:#189AB4,color:#fff
|
||||
style Agents fill:#8B0000,color:#fff
|
||||
style Input fill:#8B0000,color:#fff
|
||||
style Output fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## AI Agents with Memory
|
||||
|
||||
Create AI agents with memory capabilities for maintaining context and information across tasks.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Memory
|
||||
direction TB
|
||||
STM[Short Term]
|
||||
LTM[Long Term]
|
||||
end
|
||||
|
||||
subgraph Store
|
||||
direction TB
|
||||
DB[(Vector DB)]
|
||||
end
|
||||
|
||||
Input[Input] ---> Agents
|
||||
subgraph Agents
|
||||
direction LR
|
||||
A1[Agent 1]
|
||||
A2[Agent 2]
|
||||
A3[Agent 3]
|
||||
end
|
||||
Agents ---> Output[Output]
|
||||
|
||||
Memory <--> Store
|
||||
Store <--> A1
|
||||
Store <--> A2
|
||||
Store <--> A3
|
||||
|
||||
style Memory fill:#189AB4,color:#fff
|
||||
style Store fill:#2E8B57,color:#fff
|
||||
style Agents fill:#8B0000,color:#fff
|
||||
style Input fill:#8B0000,color:#fff
|
||||
style Output fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## AI Agents with Different Processes
|
||||
|
||||
### Sequential Process
|
||||
|
||||
The simplest form of task execution where tasks are performed one after another.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Input[Input] --> A1
|
||||
subgraph Agents
|
||||
direction LR
|
||||
A1[Agent 1] --> A2[Agent 2] --> A3[Agent 3]
|
||||
end
|
||||
A3 --> Output[Output]
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Input,Output input
|
||||
class A1,A2,A3 process
|
||||
class Agents transparent
|
||||
```
|
||||
|
||||
### Hierarchical Process
|
||||
|
||||
Uses a manager agent to coordinate task execution and agent assignments.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Input[Input] --> Manager
|
||||
|
||||
subgraph Agents
|
||||
Manager[Manager Agent]
|
||||
|
||||
subgraph Workers
|
||||
direction LR
|
||||
W1[Worker 1]
|
||||
W2[Worker 2]
|
||||
W3[Worker 3]
|
||||
end
|
||||
|
||||
Manager --> W1
|
||||
Manager --> W2
|
||||
Manager --> W3
|
||||
end
|
||||
|
||||
W1 --> Manager
|
||||
W2 --> Manager
|
||||
W3 --> Manager
|
||||
Manager --> Output[Output]
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Input,Output input
|
||||
class Manager,W1,W2,W3 process
|
||||
class Agents,Workers transparent
|
||||
```
|
||||
|
||||
### Workflow Process
|
||||
|
||||
Advanced process type supporting complex task relationships and conditional execution.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Input[Input] --> Start
|
||||
|
||||
subgraph Workflow
|
||||
direction LR
|
||||
Start[Start] --> C1{Condition}
|
||||
C1 --> |Yes| A1[Agent 1]
|
||||
C1 --> |No| A2[Agent 2]
|
||||
A1 --> Join
|
||||
A2 --> Join
|
||||
Join --> A3[Agent 3]
|
||||
end
|
||||
|
||||
A3 --> Output[Output]
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef decision fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Input,Output input
|
||||
class Start,A1,A2,A3,Join process
|
||||
class C1 decision
|
||||
class Workflow transparent
|
||||
```
|
||||
|
||||
#### Agentic Routing Workflow
|
||||
|
||||
Create AI agents that can dynamically route tasks to specialized LLM instances.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> Router[LLM Call Router]
|
||||
Router --> LLM1[LLM Call 1]
|
||||
Router --> LLM2[LLM Call 2]
|
||||
Router --> LLM3[LLM Call 3]
|
||||
LLM1 --> Out[Out]
|
||||
LLM2 --> Out
|
||||
LLM3 --> Out
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Router fill:#2E8B57,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Orchestrator Worker
|
||||
|
||||
Create AI agents that orchestrate and distribute tasks among specialized workers.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> Router[LLM Call Router]
|
||||
Router --> LLM1[LLM Call 1]
|
||||
Router --> LLM2[LLM Call 2]
|
||||
Router --> LLM3[LLM Call 3]
|
||||
LLM1 --> Synthesizer[Synthesizer]
|
||||
LLM2 --> Synthesizer
|
||||
LLM3 --> Synthesizer
|
||||
Synthesizer --> Out[Out]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Router fill:#2E8B57,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Synthesizer fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Autonomous Workflow
|
||||
|
||||
Create AI agents that can autonomously monitor, act, and adapt based on environment feedback.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Human[Human] <--> LLM[LLM Call]
|
||||
LLM -->|ACTION| Environment[Environment]
|
||||
Environment -->|FEEDBACK| LLM
|
||||
LLM --> Stop[Stop]
|
||||
|
||||
style Human fill:#8B0000,color:#fff
|
||||
style LLM fill:#2E8B57,color:#fff
|
||||
style Environment fill:#8B0000,color:#fff
|
||||
style Stop fill:#333,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Parallelization
|
||||
|
||||
Create AI agents that can execute tasks in parallel for improved performance.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> LLM2[LLM Call 2]
|
||||
In --> LLM1[LLM Call 1]
|
||||
In --> LLM3[LLM Call 3]
|
||||
LLM1 --> Aggregator[Aggregator]
|
||||
LLM2 --> Aggregator
|
||||
LLM3 --> Aggregator
|
||||
Aggregator --> Out[Out]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Aggregator fill:#fff,color:#000
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Prompt Chaining
|
||||
|
||||
Create AI agents with sequential prompt chaining for complex workflows.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> LLM1[LLM Call 1] --> Gate{Gate}
|
||||
Gate -->|Pass| LLM2[LLM Call 2] -->|Output 2| LLM3[LLM Call 3] --> Out[Out]
|
||||
Gate -->|Fail| Exit[Exit]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
style Exit fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Evaluator Optimizer
|
||||
|
||||
Create AI agents that can generate and optimize solutions through iterative feedback.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> Generator[LLM Call Generator]
|
||||
Generator -->|SOLUTION| Evaluator[LLM Call Evaluator] -->|ACCEPTED| Out[Out]
|
||||
Evaluator -->|REJECTED + FEEDBACK| Generator
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Generator fill:#2E8B57,color:#fff
|
||||
style Evaluator fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Repetitive Agents
|
||||
|
||||
Create AI agents that can efficiently handle repetitive tasks through automated loops.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> LoopAgent[("Looping Agent")]
|
||||
LoopAgent --> Task[Task]
|
||||
Task --> |Next iteration| LoopAgent
|
||||
Task --> |Done| Out[Output]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style LoopAgent fill:#2E8B57,color:#fff,shape:circle
|
||||
style Task fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## Adding Models
|
||||
|
||||
<div align="center">
|
||||
<a href="https://docs.praison.ai/models">
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/%F0%9F%93%9A_Models-Visit_docs.praison.ai-blue?style=for-the-badge&logo=bookstack&logoColor=white" alt="Models" />
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Ollama Integration
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
@@ -147,267 +481,16 @@ 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 align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="docs/images/architecture-dark.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="docs/images/architecture-light.png" />
|
||||
<img alt="PraisonAI Architecture" src="docs/images/architecture-light.png" />
|
||||
</picture>
|
||||
</div>
|
||||
|
||||
## Different User Interfaces:
|
||||
|
||||
| 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) |
|
||||
| **Realtime** | Real-time voice interaction with AI | [https://docs.praison.ai/ui/realtime](https://docs.praison.ai/ui/realtime) |
|
||||
|
||||
| Other Features | Description | Docs |
|
||||
|---|---|---|
|
||||
| **Train** | Fine-tune LLMs using your custom data | [https://docs.praison.ai/train](https://docs.praison.ai/train) |
|
||||
|
||||
|
||||
## 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> |
|
||||
|
||||
## Installation Options
|
||||
|
||||
### Using pip
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
|
||||
### Framework-specific Installation
|
||||
```bash
|
||||
# Install with CrewAI support
|
||||
pip install "praisonai[crewai]"
|
||||
|
||||
# Install with AutoGen support
|
||||
pip install "praisonai[autogen]"
|
||||
|
||||
# Install with both frameworks
|
||||
pip install "praisonai[crewai,autogen]"
|
||||
```
|
||||
|
||||
### UI and Additional Features
|
||||
```bash
|
||||
# Install UI support
|
||||
pip install "praisonai[ui]"
|
||||
|
||||
# Install Chat interface
|
||||
pip install "praisonai[chat]"
|
||||
|
||||
# Install Code interface
|
||||
pip install "praisonai[code]"
|
||||
|
||||
# Install Realtime voice interaction
|
||||
pip install "praisonai[realtime]"
|
||||
|
||||
# Install Call feature
|
||||
pip install "praisonai[call]"
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Set your OpenAI API key
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
|
||||
# Initialize with CrewAI (default)
|
||||
praisonai --init "create a movie script about dog in moon"
|
||||
|
||||
# Or initialize with AutoGen
|
||||
praisonai --framework autogen --init "create a movie script about dog in moon"
|
||||
|
||||
# Run the agents
|
||||
praisonai
|
||||
```
|
||||
|
||||
## Full Automatic Mode
|
||||
|
||||
```bash
|
||||
# With CrewAI (default)
|
||||
praisonai --auto "create a movie script about Dog in Moon"
|
||||
|
||||
# With AutoGen
|
||||
praisonai --framework autogen --auto "create a movie script about Dog in Moon"
|
||||
```
|
||||
|
||||
## Framework-specific Features
|
||||
|
||||
### CrewAI
|
||||
When installing with `pip install "praisonai[crewai]"`, you get:
|
||||
- CrewAI framework support
|
||||
- PraisonAI tools integration
|
||||
- Task delegation capabilities
|
||||
- Sequential and parallel task execution
|
||||
|
||||
### AutoGen
|
||||
When installing with `pip install "praisonai[autogen]"`, you get:
|
||||
- AutoGen framework support
|
||||
- PraisonAI tools integration
|
||||
- Multi-agent conversation capabilities
|
||||
- Code execution environment
|
||||
|
||||
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Initialise](#initialise)
|
||||
- [Run](#run)
|
||||
- [Full Automatic Mode](#full-automatic-mode)
|
||||
- [User Interface](#user-interface)
|
||||
- [Praison AI Chat](#praison-ai-chat)
|
||||
- [Create Custom Tools](#create-custom-tools)
|
||||
- [Agents Playbook](#agents-playbook)
|
||||
- [Include praisonai package in your project](#include-praisonai-package-in-your-project)
|
||||
- [Commands to Install Dev Dependencies](#commands-to-install-dependencies)
|
||||
- [Other Models](#other-models)
|
||||
- [Contributing](#contributing)
|
||||
- [Star History](#star-history)
|
||||
|
||||
## Installation Multi Agents
|
||||
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
|
||||
## Initialise
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
```
|
||||
|
||||
Generate your OPENAI API KEY from here: https://platform.openai.com/api-keys
|
||||
|
||||
Note: You can use other providers such as Ollama, Mistral ... etc. Details are provided at the bottom.
|
||||
|
||||
```bash
|
||||
praisonai --init create a movie script about dog in moon
|
||||
```
|
||||
|
||||
This will automatically create agents.yaml file in the current directory.
|
||||
|
||||
### To initialise with a specific agent framework (Optional):
|
||||
|
||||
```bash
|
||||
praisonai --framework autogen --init create movie script about cat in mars
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
praisonai
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
python -m praisonai
|
||||
```
|
||||
|
||||
### Specify the agent framework (Optional):
|
||||
|
||||
```bash
|
||||
praisonai --framework autogen
|
||||
```
|
||||
|
||||
### Full Automatic Mode
|
||||
|
||||
```bash
|
||||
praisonai --auto create a movie script about Dog in Moon
|
||||
```
|
||||
|
||||
## User Interface
|
||||
|
||||
## PraisonAI User Interfaces:
|
||||
|
||||
| Interface | Description | URL |
|
||||
| --------- | ------------------------------------------ | --------------------------------------------------------------------- |
|
||||
| **UI** | Multi Agents such as CrewAI or AutoGen | [https://docs.praisonai.com/ui/ui](https://docs.praison.ai/ui/ui) |
|
||||
| **Chat** | Chat with 100+ LLMs, single AI Agent | [https://docs.praisonai.com/ui/chat](https://docs.praison.ai/ui/chat) |
|
||||
| **Code** | Chat with entire Codebase, single AI Agent | [https://docs.praisonai.com/ui/code](https://docs.praison.ai/ui/code) |
|
||||
|
||||
```bash
|
||||
pip install -U "praisonai[ui]"
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
chainlit create-secret
|
||||
export CHAINLIT_AUTH_SECRET=xxxxxxxx
|
||||
praisonai ui
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
python -m praisonai ui
|
||||
```
|
||||
|
||||
## Praison AI Chat
|
||||
|
||||
- https://docs.praison.ai/chat/
|
||||
|
||||
```bash
|
||||
pip install "praisonai[chat]"
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
praisonai chat
|
||||
```
|
||||
|
||||
### Internet Search
|
||||
|
||||
Praison AI Chat and Praison AI Code now includes internet search capabilities using Crawl4AI and Tavily, allowing you to retrieve up-to-date information during your conversations.
|
||||
|
||||
### Vision Language Model Support
|
||||
|
||||
You can now upload images and ask questions based on them using Vision Language Models. This feature enables visual understanding and analysis within your chat sessions.
|
||||
|
||||
## Praison AI Code
|
||||
|
||||
```bash
|
||||
pip install "praisonai[code]"
|
||||
export OPENAI_API_KEY="Enter your API key"
|
||||
praisonai code
|
||||
```
|
||||
|
||||
### Internet Search
|
||||
|
||||
Praison AI Code also includes internet search functionality, enabling you to find relevant code snippets and programming information online.
|
||||
|
||||
## Create Custom Tools
|
||||
|
||||
- https://docs.praison.ai/tools/custom/
|
||||
## No Code Options
|
||||
|
||||
## Agents Playbook
|
||||
|
||||
### Simple Playbook Example
|
||||
|
||||
Create `agents.yaml` file and add the code below:
|
||||
|
||||
```yaml
|
||||
framework: crewai
|
||||
framework: praisonai
|
||||
topic: Artificial Intelligence
|
||||
roles:
|
||||
screenwriter:
|
||||
@@ -420,62 +503,25 @@ roles:
|
||||
expected_output: "Complete script ready for production."
|
||||
```
|
||||
|
||||
*To run the playbook:*
|
||||
```bash
|
||||
praisonai agents.yaml
|
||||
```
|
||||
|
||||
## Use 100+ Models
|
||||
|
||||
- https://docs.praison.ai/models/
|
||||
<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>
|
||||
|
||||
## Include praisonai package in your project
|
||||
## Development:
|
||||
|
||||
- https://docs.praison.ai/developers/wrapper
|
||||
- https://docs.praison.ai/developers/wrapper-tools/
|
||||
|
||||
## Option 1: Using RAW YAML
|
||||
|
||||
```python
|
||||
from praisonai import PraisonAI
|
||||
|
||||
# Example agent_yaml content
|
||||
agent_yaml = """
|
||||
framework: "crewai"
|
||||
topic: "Space Exploration"
|
||||
|
||||
roles:
|
||||
astronomer:
|
||||
role: "Space Researcher"
|
||||
goal: "Discover new insights about {topic}"
|
||||
backstory: "You are a curious and dedicated astronomer with a passion for unraveling the mysteries of the cosmos."
|
||||
tasks:
|
||||
investigate_exoplanets:
|
||||
description: "Research and compile information about exoplanets discovered in the last decade."
|
||||
expected_output: "A summarized report on exoplanet discoveries, including their size, potential habitability, and distance from Earth."
|
||||
"""
|
||||
|
||||
# Create a PraisonAI instance with the agent_yaml content
|
||||
praisonai = PraisonAI(agent_yaml=agent_yaml)
|
||||
|
||||
# Run PraisonAI
|
||||
result = praisonai.run()
|
||||
|
||||
# Print the result
|
||||
print(result)
|
||||
```
|
||||
|
||||
## Option 2: Using separate agents.yaml file
|
||||
|
||||
Note: Please create agents.yaml file before hand.
|
||||
|
||||
```python
|
||||
from praisonai import PraisonAI
|
||||
|
||||
def basic(): # Basic Mode
|
||||
praisonai = PraisonAI(agent_file="agents.yaml")
|
||||
praisonai.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
basic()
|
||||
```
|
||||
|
||||
## Commands to Install Dependencies:
|
||||
Below is used for development only.
|
||||
|
||||
### Using uv
|
||||
```bash
|
||||
@@ -500,18 +546,34 @@ uv pip install -r pyproject.toml --extra "crewai,autogen"
|
||||
- Submit a pull request via GitHub's web interface.
|
||||
- Await feedback from project maintainers.
|
||||
|
||||
## Other Features
|
||||
|
||||
- 🔄 Use CrewAI or AutoGen Framework
|
||||
- 💻 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
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://docs.praison.ai)
|
||||
|
||||
## License
|
||||
|
||||
Praison AI is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
|
||||
|
||||
## Video Tutorials
|
||||
|
||||
| Topic | Video |
|
||||
|-------|--------|
|
||||
| AI Agents with Self Reflection | [](https://www.youtube.com/watch?v=vLXobEN2Vc8) |
|
||||
| Reasoning Data Generating Agent | [](https://www.youtube.com/watch?v=fUT332Y2zA8) |
|
||||
| AI Agents with Reasoning | [](https://www.youtube.com/watch?v=KNDVWGN3TpM) |
|
||||
| Multimodal AI Agents | [](https://www.youtube.com/watch?v=hjAWmUT1qqY) |
|
||||
| AI Agents Workflow | [](https://www.youtube.com/watch?v=yWTH44QPl2A) |
|
||||
| Async AI Agents | [](https://www.youtube.com/watch?v=VhVQfgo00LE) |
|
||||
| Mini AI Agents | [](https://www.youtube.com/watch?v=OkvYp5aAGSg) |
|
||||
| AI Agents with Memory | [](https://www.youtube.com/watch?v=1hVfVxvPnnQ) |
|
||||
| Repetitive Agents | [](https://www.youtube.com/watch?v=dAYGxsjDOPg) |
|
||||
| Introduction | [](https://www.youtube.com/watch?v=Fn1lQjC0GO0) |
|
||||
| Tools Overview | [](https://www.youtube.com/watch?v=XaQRgRpV7jo) |
|
||||
| Custom Tools | [](https://www.youtube.com/watch?v=JSU2Rndh06c) |
|
||||
@@ -524,59 +586,5 @@ Praison AI is an open-sourced software licensed under the **[MIT license](https:
|
||||
| Training | [](https://www.youtube.com/watch?v=aLawE8kwCrI) |
|
||||
| Realtime Voice Interface | [](https://www.youtube.com/watch?v=frRHfevTCSw) |
|
||||
| Call Interface | [](https://www.youtube.com/watch?v=m1cwrUG2iAk) |
|
||||
| Reasoning Extract Agents | [](https://www.youtube.com/watch?v=2PPamsADjJA) |
|
||||
|
||||
## License
|
||||
|
||||
Praison AI is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
|
||||
|
||||
## Local Docker Development with Live Reload
|
||||
|
||||
To facilitate local development with live reload, you can use Docker. Follow the steps below:
|
||||
|
||||
1. **Create a `Dockerfile.dev`**:
|
||||
```dockerfile
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN pip install flask praisonai==2.0.18 watchdog
|
||||
|
||||
EXPOSE 5555
|
||||
|
||||
ENV FLASK_ENV=development
|
||||
|
||||
CMD ["flask", "run", "--host=0.0.0.0"]
|
||||
```
|
||||
|
||||
2. **Create a `docker-compose.yml`**:
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
volumes:
|
||||
- .:/app
|
||||
ports:
|
||||
- "5555:5555"
|
||||
environment:
|
||||
FLASK_ENV: development
|
||||
command: flask run --host=0.0.0.0
|
||||
|
||||
watch:
|
||||
image: alpine:latest
|
||||
volumes:
|
||||
- .:/app
|
||||
command: sh -c "apk add --no-cache inotify-tools && while inotifywait -r -e modify,create,delete /app; do kill -HUP 1; done"
|
||||
```
|
||||
|
||||
3. **Run Docker Compose**:
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
This setup will allow you to develop locally with live reload, making it easier to test and iterate on your code.
|
||||
@@ -1,8 +0,0 @@
|
||||
1. Make minimal code changes as possible
|
||||
2. if you are creating function, make sure to name it in more easy, user friendly , optimised manner.
|
||||
3. Never copy the exact code if presented with a code from other location or file or codebase, just make it optimised
|
||||
4. Always Follow the principle LESS IS MORE
|
||||
5. Make it minimal change as possible
|
||||
6. Firstly try not to make any modification to the existing code as possible
|
||||
7. Only modify the existing code if its highly required, without that if it cant be done, then add new code section.
|
||||
8. If you are adding new code, make sure to add it in a way that it can be easily integrated with the existing codebase.
|
||||
@@ -1,4 +0,0 @@
|
||||
"""Agent module for AI agents"""
|
||||
from .agent import Agent
|
||||
|
||||
__all__ = ['Agent']
|
||||
@@ -1,834 +0,0 @@
|
||||
import os
|
||||
import time
|
||||
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,
|
||||
display_instruction,
|
||||
display_interaction,
|
||||
display_generating,
|
||||
display_self_reflection,
|
||||
ReflectionOutput,
|
||||
client,
|
||||
error_logs,
|
||||
adisplay_instruction
|
||||
)
|
||||
import inspect
|
||||
import uuid
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..task.task import Task
|
||||
|
||||
class Agent:
|
||||
def _generate_tool_definition(self, function_name):
|
||||
"""
|
||||
Generate a tool definition from a function name by inspecting the function.
|
||||
"""
|
||||
logging.debug(f"Attempting to generate tool definition for: {function_name}")
|
||||
|
||||
# First try to get the tool definition if it exists
|
||||
tool_def_name = f"{function_name}_definition"
|
||||
tool_def = globals().get(tool_def_name)
|
||||
logging.debug(f"Looking for {tool_def_name} in globals: {tool_def is not None}")
|
||||
|
||||
if not tool_def:
|
||||
import __main__
|
||||
tool_def = getattr(__main__, tool_def_name, None)
|
||||
logging.debug(f"Looking for {tool_def_name} in __main__: {tool_def is not None}")
|
||||
|
||||
if tool_def:
|
||||
logging.debug(f"Found tool definition: {tool_def}")
|
||||
return tool_def
|
||||
|
||||
# Try to find the function in the agent's tools list first
|
||||
func = None
|
||||
for tool in self.tools:
|
||||
if callable(tool) and getattr(tool, '__name__', '') == function_name:
|
||||
func = tool
|
||||
break
|
||||
|
||||
logging.debug(f"Looking for {function_name} in agent tools: {func is not None}")
|
||||
|
||||
# If not found in tools, try globals and main
|
||||
if not func:
|
||||
func = globals().get(function_name)
|
||||
logging.debug(f"Looking for {function_name} in globals: {func is not None}")
|
||||
|
||||
if not func:
|
||||
import __main__
|
||||
func = getattr(__main__, function_name, None)
|
||||
logging.debug(f"Looking for {function_name} in __main__: {func is not None}")
|
||||
|
||||
if not func or not callable(func):
|
||||
logging.debug(f"Function {function_name} not found or not callable")
|
||||
return None
|
||||
|
||||
import inspect
|
||||
# Langchain tools
|
||||
if inspect.isclass(func) and hasattr(func, 'run') and not hasattr(func, '_run'):
|
||||
original_func = func
|
||||
func = func.run
|
||||
function_name = original_func.__name__
|
||||
# CrewAI tools
|
||||
elif inspect.isclass(func) and hasattr(func, '_run'):
|
||||
original_func = func
|
||||
func = func._run
|
||||
function_name = original_func.__name__
|
||||
|
||||
sig = inspect.signature(func)
|
||||
logging.debug(f"Function signature: {sig}")
|
||||
|
||||
# Skip self, *args, **kwargs, so they don't get passed in arguments
|
||||
parameters_list = []
|
||||
for name, param in sig.parameters.items():
|
||||
if name == "self":
|
||||
continue
|
||||
if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD):
|
||||
continue
|
||||
parameters_list.append((name, param))
|
||||
|
||||
parameters = {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
|
||||
# Parse docstring for parameter descriptions
|
||||
docstring = inspect.getdoc(func)
|
||||
logging.debug(f"Function docstring: {docstring}")
|
||||
|
||||
param_descriptions = {}
|
||||
if docstring:
|
||||
import re
|
||||
param_section = re.split(r'\s*Args:\s*', docstring)
|
||||
logging.debug(f"Param section split: {param_section}")
|
||||
if len(param_section) > 1:
|
||||
param_lines = param_section[1].split('\n')
|
||||
for line in param_lines:
|
||||
line = line.strip()
|
||||
if line and ':' in line:
|
||||
param_name, param_desc = line.split(':', 1)
|
||||
param_descriptions[param_name.strip()] = param_desc.strip()
|
||||
|
||||
logging.debug(f"Parameter descriptions: {param_descriptions}")
|
||||
|
||||
for name, param in parameters_list:
|
||||
param_type = "string" # Default type
|
||||
if param.annotation != inspect.Parameter.empty:
|
||||
if param.annotation == int:
|
||||
param_type = "integer"
|
||||
elif param.annotation == float:
|
||||
param_type = "number"
|
||||
elif param.annotation == bool:
|
||||
param_type = "boolean"
|
||||
elif param.annotation == list:
|
||||
param_type = "array"
|
||||
elif param.annotation == dict:
|
||||
param_type = "object"
|
||||
|
||||
param_info = {"type": param_type}
|
||||
if name in param_descriptions:
|
||||
param_info["description"] = param_descriptions[name]
|
||||
|
||||
parameters["properties"][name] = param_info
|
||||
if param.default == inspect.Parameter.empty:
|
||||
parameters["required"].append(name)
|
||||
|
||||
logging.debug(f"Generated parameters: {parameters}")
|
||||
|
||||
# Extract description from docstring
|
||||
description = docstring.split('\n')[0] if docstring else f"Function {function_name}"
|
||||
|
||||
tool_def = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": function_name,
|
||||
"description": description,
|
||||
"parameters": parameters
|
||||
}
|
||||
}
|
||||
logging.debug(f"Generated tool definition: {tool_def}")
|
||||
return tool_def
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
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,
|
||||
max_rpm: Optional[int] = None,
|
||||
max_execution_time: Optional[int] = None,
|
||||
memory: Optional[Any] = None,
|
||||
verbose: bool = True,
|
||||
allow_delegation: bool = False,
|
||||
step_callback: Optional[Any] = None,
|
||||
cache: bool = True,
|
||||
system_template: Optional[str] = None,
|
||||
prompt_template: Optional[str] = None,
|
||||
response_template: Optional[str] = None,
|
||||
allow_code_execution: Optional[bool] = False,
|
||||
max_retry_limit: int = 2,
|
||||
respect_context_window: bool = True,
|
||||
code_execution_mode: Literal["safe", "unsafe"] = "safe",
|
||||
embedder_config: Optional[Dict[str, Any]] = None,
|
||||
knowledge: Optional[List[str]] = None,
|
||||
knowledge_config: Optional[Dict[str, Any]] = None,
|
||||
use_system_prompt: Optional[bool] = True,
|
||||
markdown: bool = True,
|
||||
self_reflect: bool = False,
|
||||
max_reflect: int = 3,
|
||||
min_reflect: int = 1,
|
||||
reflect_llm: Optional[str] = None,
|
||||
user_id: Optional[str] = None
|
||||
):
|
||||
# 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
|
||||
self.max_rpm = max_rpm
|
||||
self.max_execution_time = max_execution_time
|
||||
self.memory = memory
|
||||
self.verbose = verbose
|
||||
self.allow_delegation = allow_delegation
|
||||
self.step_callback = step_callback
|
||||
self.cache = cache
|
||||
self.system_template = system_template
|
||||
self.prompt_template = prompt_template
|
||||
self.response_template = response_template
|
||||
self.allow_code_execution = allow_code_execution
|
||||
self.max_retry_limit = max_retry_limit
|
||||
self.respect_context_window = respect_context_window
|
||||
self.code_execution_mode = code_execution_mode
|
||||
self.embedder_config = embedder_config
|
||||
self.knowledge = knowledge
|
||||
self.use_system_prompt = use_system_prompt
|
||||
self.chat_history = []
|
||||
self.markdown = markdown
|
||||
self.max_reflect = max_reflect
|
||||
self.min_reflect = min_reflect
|
||||
# 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}
|
||||
"""
|
||||
|
||||
# Generate unique IDs
|
||||
self.agent_id = str(uuid.uuid4())
|
||||
|
||||
# Store user_id
|
||||
self.user_id = user_id
|
||||
|
||||
# Check if knowledge parameter has any values
|
||||
if not knowledge:
|
||||
self.knowledge = None
|
||||
else:
|
||||
# Initialize Knowledge with provided or default config
|
||||
from praisonaiagents.knowledge import Knowledge
|
||||
self.knowledge = Knowledge(knowledge_config or None)
|
||||
|
||||
# Handle knowledge
|
||||
if knowledge:
|
||||
for source in knowledge:
|
||||
self._process_knowledge(source)
|
||||
|
||||
def _process_knowledge(self, knowledge_item):
|
||||
"""Process and store knowledge from a file path, URL, or string."""
|
||||
try:
|
||||
if os.path.exists(knowledge_item):
|
||||
# It's a file path
|
||||
self.knowledge.add(knowledge_item, user_id=self.user_id, agent_id=self.agent_id)
|
||||
elif knowledge_item.startswith("http://") or knowledge_item.startswith("https://"):
|
||||
# It's a URL
|
||||
pass
|
||||
else:
|
||||
# It's a string content
|
||||
self.knowledge.store(knowledge_item, user_id=self.user_id, agent_id=self.agent_id)
|
||||
except Exception as e:
|
||||
logging.error(f"Error processing knowledge item: {knowledge_item}, error: {e}")
|
||||
|
||||
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):
|
||||
"""
|
||||
Execute a tool dynamically based on the function name and arguments.
|
||||
"""
|
||||
logging.debug(f"{self.name} executing tool {function_name} with arguments: {arguments}")
|
||||
|
||||
# Try to find the function in the agent's tools list first
|
||||
func = None
|
||||
for tool in self.tools:
|
||||
if (callable(tool) and getattr(tool, '__name__', '') == function_name) or \
|
||||
(inspect.isclass(tool) and tool.__name__ == function_name):
|
||||
func = tool
|
||||
break
|
||||
|
||||
if func is None:
|
||||
# If not found in tools, try globals and main
|
||||
func = globals().get(function_name)
|
||||
if not func:
|
||||
import __main__
|
||||
func = getattr(__main__, function_name, None)
|
||||
|
||||
if func:
|
||||
try:
|
||||
# Langchain: If it's a class with run but not _run, instantiate and call run
|
||||
if inspect.isclass(func) and hasattr(func, 'run') and not hasattr(func, '_run'):
|
||||
instance = func()
|
||||
run_params = {k: v for k, v in arguments.items()
|
||||
if k in inspect.signature(instance.run).parameters
|
||||
and k != 'self'}
|
||||
return instance.run(**run_params)
|
||||
|
||||
# CrewAI: If it's a class with an _run method, instantiate and call _run
|
||||
elif inspect.isclass(func) and hasattr(func, '_run'):
|
||||
instance = func()
|
||||
run_params = {k: v for k, v in arguments.items()
|
||||
if k in inspect.signature(instance._run).parameters
|
||||
and k != 'self'}
|
||||
return instance._run(**run_params)
|
||||
|
||||
# Otherwise treat as regular function
|
||||
elif callable(func):
|
||||
return func(**arguments)
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
logging.error(f"Error executing tool {function_name}: {error_msg}")
|
||||
return {"error": error_msg}
|
||||
|
||||
error_msg = f"Tool '{function_name}' is not callable"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def clear_history(self):
|
||||
self.chat_history = []
|
||||
|
||||
def __str__(self):
|
||||
return f"Agent(name='{self.name}', role='{self.role}', goal='{self.goal}')"
|
||||
|
||||
def _chat_completion(self, messages, temperature=0.2, tools=None, stream=True):
|
||||
start_time = time.time()
|
||||
logging.debug(f"{self.name} sending messages to LLM: {messages}")
|
||||
|
||||
formatted_tools = []
|
||||
if tools is None:
|
||||
tools = self.tools
|
||||
if tools:
|
||||
for tool in tools:
|
||||
if isinstance(tool, str):
|
||||
# Generate tool definition for string tool names
|
||||
tool_def = self._generate_tool_definition(tool)
|
||||
if tool_def:
|
||||
formatted_tools.append(tool_def)
|
||||
else:
|
||||
logging.warning(f"Could not generate definition for tool: {tool}")
|
||||
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__))
|
||||
else:
|
||||
logging.warning(f"Tool {tool} not recognized")
|
||||
|
||||
try:
|
||||
initial_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
tools=formatted_tools if formatted_tools else None,
|
||||
stream=False
|
||||
)
|
||||
|
||||
tool_calls = getattr(initial_response.choices[0].message, 'tool_calls', None)
|
||||
|
||||
if tool_calls:
|
||||
messages.append({
|
||||
"role": "assistant",
|
||||
"content": initial_response.choices[0].message.content,
|
||||
"tool_calls": tool_calls
|
||||
})
|
||||
|
||||
for tool_call in tool_calls:
|
||||
function_name = tool_call.function.name
|
||||
arguments = json.loads(tool_call.function.arguments)
|
||||
|
||||
if self.verbose:
|
||||
display_tool_call(f"Agent {self.name} is calling function '{function_name}' with arguments: {arguments}")
|
||||
|
||||
tool_result = self.execute_tool(function_name, arguments)
|
||||
results_str = json.dumps(tool_result) if tool_result else "Function returned an empty output"
|
||||
|
||||
if self.verbose:
|
||||
display_tool_call(f"Function '{function_name}' returned: {results_str}")
|
||||
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
"content": results_str
|
||||
})
|
||||
|
||||
if stream:
|
||||
response_stream = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=True
|
||||
)
|
||||
full_response_text = ""
|
||||
|
||||
# Create Live display with proper configuration
|
||||
with Live(
|
||||
display_generating("", start_time),
|
||||
console=self.console,
|
||||
refresh_per_second=4,
|
||||
transient=True, # Changed to False to preserve output
|
||||
vertical_overflow="ellipsis",
|
||||
auto_refresh=True
|
||||
) as live:
|
||||
for chunk in response_stream:
|
||||
if chunk.choices[0].delta.content:
|
||||
full_response_text += chunk.choices[0].delta.content
|
||||
live.update(display_generating(full_response_text, start_time))
|
||||
|
||||
# Clear the last generating display with a blank line
|
||||
self.console.print()
|
||||
|
||||
final_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False
|
||||
)
|
||||
return final_response
|
||||
else:
|
||||
if tool_calls:
|
||||
final_response = client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False
|
||||
)
|
||||
return final_response
|
||||
else:
|
||||
return initial_response
|
||||
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
return None
|
||||
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
|
||||
# Search for existing knowledge if any knowledge is provided
|
||||
if self.knowledge:
|
||||
search_results = self.knowledge.search(prompt, agent_id=self.agent_id)
|
||||
if search_results:
|
||||
# Check if search_results is a list of dictionaries or strings
|
||||
if isinstance(search_results, dict) and 'results' in search_results:
|
||||
# Extract memory content from the results
|
||||
knowledge_content = "\n".join([result['memory'] for result in search_results['results']])
|
||||
else:
|
||||
# If search_results is a list of strings, join them directly
|
||||
knowledge_content = "\n".join(search_results)
|
||||
|
||||
# Append found knowledge to the prompt
|
||||
prompt = f"{prompt}\n\nKnowledge: {knowledge_content}"
|
||||
|
||||
if self.use_system_prompt:
|
||||
system_prompt = f"""{self.backstory}\n
|
||||
Your Role: {self.role}\n
|
||||
Your Goal: {self.goal}
|
||||
"""
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {json.dumps(output_json.model_json_schema())}"
|
||||
elif output_pydantic:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {json.dumps(output_pydantic.model_json_schema())}"
|
||||
else:
|
||||
system_prompt = None
|
||||
|
||||
messages = []
|
||||
if system_prompt:
|
||||
messages.append({"role": "system", "content": system_prompt})
|
||||
messages.extend(self.chat_history)
|
||||
|
||||
# Modify prompt if output_json or output_pydantic is specified
|
||||
original_prompt = prompt
|
||||
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):
|
||||
# For multimodal prompts, append to the text content
|
||||
for item in prompt:
|
||||
if item["type"] == "text":
|
||||
item["text"] += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
break
|
||||
|
||||
if isinstance(prompt, list):
|
||||
# If we receive a multimodal prompt list, place it directly in the user message
|
||||
messages.append({"role": "user", "content": prompt})
|
||||
else:
|
||||
messages.append({"role": "user", "content": prompt})
|
||||
|
||||
final_response_text = None
|
||||
reflection_count = 0
|
||||
start_time = time.time()
|
||||
|
||||
while True:
|
||||
try:
|
||||
if self.verbose:
|
||||
# Handle both string and list prompts for instruction display
|
||||
display_text = prompt
|
||||
if isinstance(prompt, list):
|
||||
# Extract text content from multimodal prompt
|
||||
display_text = next((item["text"] for item in prompt if item["type"] == "text"), "")
|
||||
|
||||
if display_text and str(display_text).strip():
|
||||
# Pass agent information to display_instruction
|
||||
agent_tools = [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools]
|
||||
display_instruction(
|
||||
f"Agent {self.name} is processing prompt: {display_text}",
|
||||
console=self.console,
|
||||
agent_name=self.name,
|
||||
agent_role=self.role,
|
||||
agent_tools=agent_tools
|
||||
)
|
||||
|
||||
response = self._chat_completion(messages, temperature=temperature, tools=tools if tools else None)
|
||||
if not response:
|
||||
return None
|
||||
|
||||
tool_calls = getattr(response.choices[0].message, 'tool_calls', None)
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
if tool_calls:
|
||||
messages.append({
|
||||
"role": "assistant",
|
||||
"content": response_text,
|
||||
"tool_calls": tool_calls
|
||||
})
|
||||
|
||||
for tool_call in tool_calls:
|
||||
function_name = tool_call.function.name
|
||||
arguments = json.loads(tool_call.function.arguments)
|
||||
|
||||
if self.verbose:
|
||||
display_tool_call(f"Agent {self.name} is calling function '{function_name}' with arguments: {arguments}", console=self.console)
|
||||
|
||||
tool_result = self.execute_tool(function_name, arguments)
|
||||
|
||||
if tool_result:
|
||||
if self.verbose:
|
||||
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=self.console)
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
"content": json.dumps(tool_result)
|
||||
})
|
||||
else:
|
||||
messages.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
"content": "Function returned an empty output"
|
||||
})
|
||||
|
||||
response = self._chat_completion(messages, temperature=temperature)
|
||||
if not response:
|
||||
return None
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
# 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})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
logging.debug(f"Agent {self.name} final response: {response_text}")
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
reflection_prompt = f"""
|
||||
Reflect on your previous response: '{response_text}'.
|
||||
Identify any flaws, improvements, or actions.
|
||||
Provide a "satisfactory" status ('yes' or 'no').
|
||||
Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
"""
|
||||
logging.debug(f"{self.name} reflection attempt {reflection_count+1}, sending prompt: {reflection_prompt}")
|
||||
messages.append({"role": "user", "content": reflection_prompt})
|
||||
|
||||
try:
|
||||
reflection_response = client.beta.chat.completions.parse(
|
||||
model=self.reflect_llm if self.reflect_llm else self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
response_format=ReflectionOutput
|
||||
)
|
||||
|
||||
reflection_output = reflection_response.choices[0].message.parsed
|
||||
|
||||
if self.verbose:
|
||||
display_self_reflection(f"Agent {self.name} self reflection (using {self.reflect_llm if self.reflect_llm else self.llm}): reflection='{reflection_output.reflection}' satisfactory='{reflection_output.satisfactory}'", console=self.console)
|
||||
|
||||
messages.append({"role": "assistant", "content": f"Self Reflection: {reflection_output.reflection} Satisfactory?: {reflection_output.satisfactory}"})
|
||||
|
||||
# Only consider satisfactory after minimum reflections
|
||||
if reflection_output.satisfactory == "yes" and reflection_count >= self.min_reflect - 1:
|
||||
if self.verbose:
|
||||
display_self_reflection("Agent marked the response as satisfactory after meeting minimum reflections", console=self.console)
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
# Check if we've hit max reflections
|
||||
if reflection_count >= self.max_reflect - 1:
|
||||
if self.verbose:
|
||||
display_self_reflection("Maximum reflection count reached, returning current response", console=self.console)
|
||||
self.chat_history.append({"role": "user", "content": prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
logging.debug(f"{self.name} reflection count {reflection_count + 1}, continuing reflection process")
|
||||
messages.append({"role": "user", "content": "Now regenerate your response using the reflection you made"})
|
||||
response = self._chat_completion(messages, temperature=temperature, tools=None, stream=True)
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
reflection_count += 1
|
||||
continue # Continue the loop for more reflections
|
||||
|
||||
except Exception as e:
|
||||
display_error(f"Error in parsing self-reflection json {e}. Retrying", console=self.console)
|
||||
logging.error("Reflection parsing failed.", exc_info=True)
|
||||
messages.append({"role": "assistant", "content": f"Self Reflection failed."})
|
||||
reflection_count += 1
|
||||
continue # Continue even after error to try again
|
||||
|
||||
except Exception as e:
|
||||
display_error(f"Error in chat: {e}", console=self.console)
|
||||
return None
|
||||
|
||||
def clean_json_output(self, output: str) -> str:
|
||||
"""Clean and extract JSON from response text."""
|
||||
cleaned = output.strip()
|
||||
# Remove markdown code blocks if present
|
||||
if cleaned.startswith("```json"):
|
||||
cleaned = cleaned[len("```json"):].strip()
|
||||
if cleaned.startswith("```"):
|
||||
cleaned = cleaned[len("```"):].strip()
|
||||
if cleaned.endswith("```"):
|
||||
cleaned = cleaned[:-3].strip()
|
||||
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: {json.dumps(output_json.model_json_schema())}"
|
||||
elif output_pydantic:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {json.dumps(output_pydantic.model_json_schema())}"
|
||||
|
||||
# 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
|
||||
|
||||
# Display instruction with agent info if verbose
|
||||
if self.verbose:
|
||||
display_text = prompt
|
||||
if isinstance(prompt, list):
|
||||
display_text = next((item["text"] for item in prompt if item["type"] == "text"), "")
|
||||
|
||||
if display_text and str(display_text).strip():
|
||||
agent_tools = [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools]
|
||||
await adisplay_instruction(
|
||||
f"Agent {self.name} is processing prompt: {display_text}",
|
||||
console=self.console,
|
||||
agent_name=self.name,
|
||||
agent_role=self.role,
|
||||
agent_tools=agent_tools
|
||||
)
|
||||
|
||||
# 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
|
||||
|
||||
def run(self):
|
||||
"""Alias for start() method"""
|
||||
return self.start()
|
||||
|
||||
def start(self, prompt: str, **kwargs):
|
||||
"""Start the agent with a prompt. This is a convenience method that wraps chat()."""
|
||||
return self.chat(prompt, **kwargs)
|
||||
@@ -1,650 +0,0 @@
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Optional, List, Any, AsyncGenerator
|
||||
from pydantic import BaseModel
|
||||
from ..agent.agent import Agent
|
||||
from ..task.task import Task
|
||||
from ..main import display_error, client
|
||||
import csv
|
||||
import os
|
||||
|
||||
class LoopItems(BaseModel):
|
||||
items: List[Any]
|
||||
|
||||
class Process:
|
||||
def __init__(self, tasks: Dict[str, Task], agents: List[Agent], manager_llm: Optional[str] = None, verbose: bool = False, max_iter: int = 10):
|
||||
self.tasks = tasks
|
||||
self.agents = agents
|
||||
self.manager_llm = manager_llm
|
||||
self.verbose = verbose
|
||||
self.max_iter = max_iter
|
||||
|
||||
async def aworkflow(self) -> AsyncGenerator[str, None]:
|
||||
"""Async version of workflow method"""
|
||||
current_iter = 0 # Track how many times we've looped
|
||||
# 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:
|
||||
current_iter += 1
|
||||
if current_iter > self.max_iter:
|
||||
logging.info(f"Max iteration limit {self.max_iter} reached, ending workflow.")
|
||||
break
|
||||
|
||||
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}"
|
||||
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)
|
||||
|
||||
# Reset completed task to "not started" so it can run again
|
||||
if self.tasks[task_id].status == "completed":
|
||||
logging.debug(f"Task {task_id} was completed, resetting to 'not started' for next iteration.")
|
||||
self.tasks[task_id].status = "not started"
|
||||
|
||||
# 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 and current_task.result:
|
||||
if current_task.task_type in ["decision", "loop"]:
|
||||
# MINIMAL CHANGE: use pydantic decision if present
|
||||
decision_str = current_task.result.raw.lower()
|
||||
if current_task.result.pydantic and hasattr(current_task.result.pydantic, "decision"):
|
||||
decision_str = current_task.result.pydantic.decision.lower()
|
||||
|
||||
# Check conditions
|
||||
for condition, tasks in current_task.condition.items():
|
||||
if condition.lower() == decision_str:
|
||||
# Handle both list and direct string values
|
||||
task_value = tasks[0] if isinstance(tasks, list) else tasks
|
||||
if not task_value or task_value == "exit":
|
||||
logging.info("Workflow exit condition met, ending workflow")
|
||||
current_task = None
|
||||
break
|
||||
next_task_name = task_value
|
||||
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 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"""
|
||||
current_iter = 0 # Track how many times we've looped
|
||||
# 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")
|
||||
|
||||
# If loop type and no input_file, default to tasks.csv
|
||||
if start_task and start_task.task_type == "loop" and not start_task.input_file:
|
||||
start_task.input_file = "tasks.csv"
|
||||
|
||||
# --- If loop + input_file, read file & create tasks
|
||||
if start_task and start_task.task_type == "loop" and getattr(start_task, "input_file", None):
|
||||
try:
|
||||
file_ext = os.path.splitext(start_task.input_file)[1].lower()
|
||||
new_tasks = []
|
||||
|
||||
if file_ext == ".csv":
|
||||
# existing CSV reading logic
|
||||
with open(start_task.input_file, "r", encoding="utf-8") as f:
|
||||
# Try as simple CSV first
|
||||
reader = csv.reader(f)
|
||||
previous_task = None
|
||||
for i, row in enumerate(reader):
|
||||
if row: # Skip empty rows
|
||||
task_desc = row[0] # Take first column
|
||||
row_task = Task(
|
||||
description=task_desc, # Keep full row as description
|
||||
agent=start_task.agent,
|
||||
name=task_desc, # Use first column as name
|
||||
is_start=(i == 0),
|
||||
task_type="task",
|
||||
condition={
|
||||
"complete": ["next"],
|
||||
"retry": ["current"]
|
||||
}
|
||||
)
|
||||
self.tasks[row_task.id] = row_task
|
||||
new_tasks.append(row_task)
|
||||
|
||||
if previous_task:
|
||||
previous_task.next_tasks = [row_task.name]
|
||||
previous_task.condition["complete"] = [row_task.name]
|
||||
previous_task = row_task
|
||||
else:
|
||||
# If not CSV, read lines
|
||||
with open(start_task.input_file, "r", encoding="utf-8") as f:
|
||||
lines = f.read().splitlines()
|
||||
previous_task = None
|
||||
for i, line in enumerate(lines):
|
||||
row_task = Task(
|
||||
description=line.strip(),
|
||||
agent=start_task.agent,
|
||||
name=line.strip(),
|
||||
is_start=(i == 0),
|
||||
task_type="task",
|
||||
condition={
|
||||
"complete": ["next"],
|
||||
"retry": ["current"]
|
||||
}
|
||||
)
|
||||
self.tasks[row_task.id] = row_task
|
||||
new_tasks.append(row_task)
|
||||
|
||||
if previous_task:
|
||||
previous_task.next_tasks = [row_task.name]
|
||||
previous_task.condition["complete"] = [row_task.name]
|
||||
previous_task = row_task
|
||||
|
||||
if new_tasks:
|
||||
start_task = new_tasks[0]
|
||||
logging.info(f"Created {len(new_tasks)} tasks from: {start_task.input_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to read file tasks: {e}")
|
||||
|
||||
# end of the new block
|
||||
current_task = start_task
|
||||
visited_tasks = set()
|
||||
loop_data = {} # Store loop-specific data
|
||||
|
||||
while current_task:
|
||||
current_iter += 1
|
||||
if current_iter > self.max_iter:
|
||||
logging.info(f"Max iteration limit {self.max_iter} reached, ending workflow.")
|
||||
break
|
||||
|
||||
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.
|
||||
# """
|
||||
# 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}"
|
||||
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)
|
||||
|
||||
# Reset completed task to "not started" so it can run again: Only for workflow because some tasks may be revisited
|
||||
if self.tasks[task_id].status == "completed":
|
||||
logging.debug(f"Task {task_id} was completed, resetting to 'not started' for next iteration.")
|
||||
self.tasks[task_id].status = "not started"
|
||||
|
||||
# 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 and current_task.result:
|
||||
if current_task.task_type in ["decision", "loop"]:
|
||||
# MINIMAL CHANGE: use pydantic decision if present
|
||||
decision_str = current_task.result.raw.lower()
|
||||
if current_task.result.pydantic and hasattr(current_task.result.pydantic, "decision"):
|
||||
decision_str = current_task.result.pydantic.decision.lower()
|
||||
|
||||
# Check conditions
|
||||
for condition, tasks in current_task.condition.items():
|
||||
if condition.lower() == decision_str:
|
||||
# Handle both list and direct string values
|
||||
task_value = tasks[0] if isinstance(tasks, list) else tasks
|
||||
if not task_value or task_value == "exit":
|
||||
logging.info("Workflow exit condition met, ending workflow")
|
||||
current_task = None
|
||||
break
|
||||
next_task_name = task_value
|
||||
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 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
|
||||
|
||||
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",
|
||||
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...")
|
||||
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")
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install flask praisonai==2.0.54 gunicorn markdown
|
||||
RUN pip install flask praisonai==2.0.71 gunicorn markdown
|
||||
EXPOSE 8080
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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.54 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.71 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
+12
-76
@@ -112,86 +112,22 @@ graph LR
|
||||
<Step title="Create Agent">
|
||||
Create `app.py`:
|
||||
<CodeGroup>
|
||||
```python Single Agent
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
```python Single Agent
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# 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"
|
||||
)
|
||||
agent = Agent(instructions="Your are a helpful AI assistant")
|
||||
agent.start("Write a movie script about a robot in Mars")
|
||||
```
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
```python Multi Agents
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
research_agent = Agent(instructions="Research about AI")
|
||||
summarise_agent = Agent(instructions="Summarise research agent's findings")
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
```python Multiple Agents
|
||||
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()
|
||||
```
|
||||
agents = PraisonAIAgents(agents=[research_agent, summarise_agent])
|
||||
agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
@@ -0,0 +1,75 @@
|
||||
---
|
||||
title: 'Local Development'
|
||||
description: 'Set up local development environment with Docker and live reload'
|
||||
---
|
||||
|
||||
## Logging
|
||||
```bash
|
||||
export LOGLEVEL=info
|
||||
```
|
||||
|
||||
Advanced logging:
|
||||
```bash
|
||||
export LOGLEVEL=debug
|
||||
```
|
||||
|
||||
## Local Docker Development with Live Reload
|
||||
|
||||
To facilitate local development with live reload, you can use Docker. Follow the steps below:
|
||||
|
||||
### 1. Create Dockerfile.dev
|
||||
|
||||
<CodeGroup>
|
||||
```dockerfile Dockerfile.dev
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN pip install flask praisonai==2.0.18 watchdog
|
||||
|
||||
EXPOSE 5555
|
||||
|
||||
ENV FLASK_ENV=development
|
||||
|
||||
CMD ["flask", "run", "--host=0.0.0.0"]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Create docker-compose.yml
|
||||
|
||||
<CodeGroup>
|
||||
```yaml docker-compose.yml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
volumes:
|
||||
- .:/app
|
||||
ports:
|
||||
- "5555:5555"
|
||||
environment:
|
||||
FLASK_ENV: development
|
||||
command: flask run --host=0.0.0.0
|
||||
|
||||
watch:
|
||||
image: alpine:latest
|
||||
volumes:
|
||||
- .:/app
|
||||
command: sh -c "apk add --no-cache inotify-tools && while inotifywait -r -e modify,create,delete /app; do kill -HUP 1; done"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 3. Run Docker Compose
|
||||
|
||||
<CodeGroup>
|
||||
```bash Terminal
|
||||
docker-compose up
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
This setup will allow you to develop locally with live reload, making it easier to test and iterate on your code.
|
||||
@@ -0,0 +1,244 @@
|
||||
---
|
||||
title: "Chat with PDF Agents"
|
||||
sidebarTitle: "Chat with PDF"
|
||||
description: "Learn how to create AI agents that can intelligently chat with PDF documents using vector databases for efficient information retrieval."
|
||||
icon: "file-pdf"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
PDF[PDF Document] --> PDFAgent[("PDF Chat Agent")]
|
||||
VDB[(Vector DB)] --> PDFAgent
|
||||
PDFAgent --> Chat[Chat Interface]
|
||||
Chat --> |Query| VDB
|
||||
Chat --> Out[Response]
|
||||
|
||||
style PDF fill:#8B0000,color:#fff
|
||||
style PDFAgent fill:#2E8B57,color:#fff,shape:circle
|
||||
style VDB fill:#4169E1,color:#fff,shape:cylinder
|
||||
style Chat fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
A PDF-centric workflow where Chat agents interact with vector databases to store and retrieve information from PDF documents, enabling natural conversations and intelligent question-answering capabilities.
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install PraisonAI Agents with PDF chat support:
|
||||
```bash
|
||||
pip install "praisonaiagents[knowledge]"
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your OpenAI API key:
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxx
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Script">
|
||||
Create a new file `chat_with_pdf.py`:
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="PDF Chat Agent",
|
||||
instructions="You answer questions based on the provided PDF document.",
|
||||
knowledge=["document.pdf"], # PDF Indexing
|
||||
)
|
||||
|
||||
agent.start("What is the main topic of this PDF?") # Chat Query
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## PDF Processing and Chat Agents
|
||||
|
||||
<Note>
|
||||
PDF processing involves indexing the document content for efficient retrieval during chat.
|
||||
</Note>
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph In[Input]
|
||||
PDF[PDF Documents]
|
||||
end
|
||||
|
||||
subgraph Router[Vector Store]
|
||||
DB[(Vector DB)]
|
||||
end
|
||||
|
||||
subgraph Out[Chat Agents]
|
||||
A1[Chat Agent 1]
|
||||
A2[Chat Agent 2]
|
||||
A3[Chat Agent 3]
|
||||
end
|
||||
|
||||
In --> Router
|
||||
Router --> A1
|
||||
Router --> A2
|
||||
Router --> A3
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Router fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
The simplest way to create a PDF chat agent is without any configuration:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="PDF Chat Agent",
|
||||
instructions="You answer questions based on the provided PDF document.",
|
||||
knowledge=["document.pdf"] # PDF Indexing
|
||||
)
|
||||
|
||||
agent.start("What are the key points in this document?") # Chat Query
|
||||
```
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
For more control over the knowledge base, you can specify a configuration:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
agent = Agent(
|
||||
name="PDF Chat Agent",
|
||||
instructions="You answer questions based on the provided PDF document.",
|
||||
knowledge=["document.pdf"], # PDF Indexing
|
||||
knowledge_config=config # Configuration
|
||||
)
|
||||
|
||||
agent.start("What is the main topic of this PDF?") # Chat Query
|
||||
```
|
||||
|
||||
### Multi-Agent Knowledge System
|
||||
|
||||
For more complex scenarios, you can create a knowledge-based system with multiple agents:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import logging
|
||||
import os
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define the configuration for the Knowledge instance
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create an agent with knowledge capabilities
|
||||
knowledge_agent = Agent(
|
||||
name="KnowledgeAgent",
|
||||
role="Information Specialist",
|
||||
goal="Store and retrieve knowledge efficiently",
|
||||
backstory="Expert in managing and utilizing stored knowledge",
|
||||
knowledge=["sample.pdf"], # Indexing
|
||||
knowledge_config=config, # Configuration
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Define a task for the agent
|
||||
knowledge_task = Task(
|
||||
name="knowledge_task",
|
||||
description="Who is Mervin Praison?",
|
||||
expected_output="Answer to the question",
|
||||
agent=knowledge_agent # Agent
|
||||
)
|
||||
|
||||
# Create and start the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[knowledge_agent],
|
||||
tasks=[knowledge_task],
|
||||
process="sequential",
|
||||
user_id="user1" # User ID
|
||||
)
|
||||
|
||||
# Start execution
|
||||
result = agents.start() # Retrieval
|
||||
```
|
||||
|
||||
## Understanding PDF Chat Agents
|
||||
|
||||
<Card title="What are PDF Chat Agents?" icon="question">
|
||||
PDF Chat agents enable:
|
||||
- Natural conversation with PDF documents
|
||||
- Intelligent information extraction
|
||||
- Context-aware document understanding
|
||||
- Quick answers to document-specific questions
|
||||
</Card>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="PDF Processing" icon="file-pdf">
|
||||
Process and index PDF documents efficiently.
|
||||
</Card>
|
||||
<Card title="Natural Chat" icon="comments">
|
||||
Have natural conversations about PDF content.
|
||||
</Card>
|
||||
<Card title="Smart Retrieval" icon="brain">
|
||||
Intelligently retrieve relevant information from PDFs.
|
||||
</Card>
|
||||
<Card title="Context Awareness" icon="layer-group">
|
||||
Maintain context throughout the conversation.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="PDF Issues" icon="triangle-exclamation">
|
||||
If PDF processing isn't working:
|
||||
- Check PDF file format and encoding
|
||||
- Verify document accessibility
|
||||
- Enable verbose mode for debugging
|
||||
</Card>
|
||||
|
||||
<Card title="Chat Issues" icon="gauge-high">
|
||||
If chat responses aren't accurate:
|
||||
- Check PDF indexing quality
|
||||
- Verify question clarity
|
||||
- Monitor context retention
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="AutoAgents" icon="robot" href="./autoagents">
|
||||
Learn about automatically created and managed AI agents
|
||||
</Card>
|
||||
<Card title="Mini Agents" icon="microchip" href="./mini">
|
||||
Explore lightweight, focused AI agents
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
For optimal chat experience, ensure your PDFs are properly formatted and text-searchable.
|
||||
</Note>
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: "Command Line Interface"
|
||||
sidebarTitle: "CLI"
|
||||
description: "Use PraisonAI directly from your terminal with simple commands"
|
||||
icon: "terminal"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Start((🚀)) --> CLI[CLI Command]
|
||||
CLI --> Agent[AI Agent]
|
||||
Agent --> Config[Config/YAML]
|
||||
Config --> Out((🏁))
|
||||
|
||||
style Start fill:#8B0000,color:#fff,stroke:#8B0000
|
||||
style CLI fill:#2E8B57,color:#fff
|
||||
style Agent fill:#2E8B57,color:#fff
|
||||
style Config fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff,stroke:#8B0000
|
||||
```
|
||||
|
||||
PraisonAI CLI provides a simple way to interact with AI agents directly from your terminal. You can run quick commands, specify LLM options, or use YAML configuration files for more complex scenarios.
|
||||
|
||||
<Frame>
|
||||
<img src="../demo/praisonai-cli-demo.gif" alt="PraisonAI CLI Demo" />
|
||||
</Frame>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install the PraisonAI package:
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
</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>
|
||||
</Steps>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Simple Command" icon="terminal" defaultOpen>
|
||||
Run a simple command directly:
|
||||
```bash
|
||||
praisonai "write a movie script in 3 lines"
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="With LLM Option" icon="wand-magic-sparkles" defaultOpen>
|
||||
Specify a different LLM model:
|
||||
```bash
|
||||
praisonai "write a movie script in 3 lines" --llm gpt-4o-mini
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Using YAML Config" icon="file-code" defaultOpen>
|
||||
Run agents defined in a YAML file:
|
||||
```bash
|
||||
praisonai agents.yaml
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Configuration
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Create Config">
|
||||
Initialize a new agents.yaml file for your project:
|
||||
```bash
|
||||
praisonai --init "Create a movie script about AI"
|
||||
```
|
||||
This will create an `agents.yaml` file with predefined configuration for your task.
|
||||
</Tab>
|
||||
|
||||
<Tab title="Auto Mode">
|
||||
Let PraisonAI automatically create and configure agents:
|
||||
```bash
|
||||
praisonai --auto "Create a movie script about AI"
|
||||
```
|
||||
This mode will analyze your task and set up appropriate agents automatically.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Simple Commands" icon="terminal">
|
||||
Run AI tasks directly from your terminal with simple commands.
|
||||
</Card>
|
||||
<Card title="LLM Options" icon="wand-magic-sparkles">
|
||||
Choose from different LLM models for your specific needs.
|
||||
</Card>
|
||||
<Card title="YAML Support" icon="file-code">
|
||||
Use YAML files for complex agent configurations and workflows.
|
||||
</Card>
|
||||
<Card title="Auto Configuration" icon="robot">
|
||||
Automatic agent setup based on task requirements.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup>
|
||||
<Card title="YAML Configuration" icon="file-code" href="/config">
|
||||
Learn more about YAML configuration options
|
||||
</Card>
|
||||
<Card title="API Reference" icon="code" href="/api-reference">
|
||||
View the complete API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,298 @@
|
||||
---
|
||||
title: "Generate Synthetic Reasoning Data Agents"
|
||||
sidebarTitle: "Generate Reasoning Data"
|
||||
description: "Learn how to generate chain-of-thought reasoning data using PraisonAI Agents."
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start[Start] --> Generator[Question Answer Generator Agent]
|
||||
Generator --> Evaluator[Evaluator Agent]
|
||||
Evaluator --> COT[Reasoning Steps / COT Generator Agent]
|
||||
COT --> COT
|
||||
COT --> Upload[HuggingFace Uploader Agent]
|
||||
Upload --> End[End]
|
||||
|
||||
style Start fill:#8B0000,color:#fff
|
||||
style Generator fill:#2E8B57,color:#fff
|
||||
style Evaluator fill:#2E8B57,color:#fff
|
||||
style COT fill:#2E8B57,color:#fff
|
||||
style Upload fill:#2E8B57,color:#fff
|
||||
style End fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## What is Chain-of-Thought Generation?
|
||||
|
||||
Chain-of-Thought (CoT) Generation is a process where AI agents create detailed, step-by-step reasoning paths for solving problems. This involves generating questions, evaluating them, producing detailed solution steps, and making the data available for training and analysis.
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]" datasets huggingface-hub pandas
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your OpenAI API key as an environment variable in your terminal:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key_here
|
||||
export HF_TOKEN=your_huggingface_token_here
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create a file">
|
||||
Create a new file `app.py` with the basic setup:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import cot_save, cot_upload_to_huggingface
|
||||
from pydantic import BaseModel
|
||||
import os
|
||||
|
||||
# Define Pydantic model for structured output
|
||||
class DecisionModel(BaseModel):
|
||||
response: str
|
||||
decision: str
|
||||
|
||||
def write_csv(file_path, data):
|
||||
"""Write data to CSV file."""
|
||||
if not os.path.exists(file_path):
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(data + '\n')
|
||||
else:
|
||||
with open(file_path, 'a') as file:
|
||||
file.write(data + '\n')
|
||||
return f"Data appended to {file_path}"
|
||||
|
||||
def count_questions(file_path):
|
||||
"""Count lines in file."""
|
||||
with open(file_path, 'r') as file:
|
||||
return sum(1 for _ in file)
|
||||
|
||||
# Create specialized agents
|
||||
qa_generator = Agent(
|
||||
name="Generator",
|
||||
role="Question Creator",
|
||||
goal="Create challenging math and logic questions",
|
||||
backstory="Expert in educational content creation",
|
||||
llm="gpt-4o-mini",
|
||||
tools=[write_csv, count_questions]
|
||||
)
|
||||
|
||||
total_questions_evaluator = Agent(
|
||||
name="TotalQuestionsEvaluator",
|
||||
role="Total Questions Evaluator",
|
||||
goal="Evaluate the total number of questions in qa_pairs.csv file",
|
||||
backstory="Expert in evaluating the total number of questions in a file",
|
||||
llm="gpt-4o-mini",
|
||||
tools=[count_questions],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
cot_generator = Agent(
|
||||
name="COTGenerator",
|
||||
role="Chain of Thought Specialist",
|
||||
goal="Generate and manage chain of thought solutions for Q&A pairs",
|
||||
backstory="Expert in breaking down problems and generating detailed solution steps",
|
||||
tools=[cot_save],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=False
|
||||
)
|
||||
|
||||
upload_to_huggingface = Agent(
|
||||
name="UploadToHuggingface",
|
||||
role="Upload to Huggingface",
|
||||
goal="Upload the generated chain of thought solutions to a Huggingface dataset",
|
||||
backstory="Expert in saving data to Huggingface",
|
||||
tools=[cot_upload_to_huggingface],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=False
|
||||
)
|
||||
|
||||
# Define tasks with workflow
|
||||
generate_task = Task(
|
||||
description="""Generate question and answer in csv format without headers: question, answer and append to qa_pairs.csv file
|
||||
generate 10 unique questions and answers and don't repeat on the same question and answer. Reponse with 'done' when done
|
||||
with append mode as 'a'
|
||||
Example question and answer:
|
||||
question, answer
|
||||
What is the sum of numbers from 1 to 10?, 55
|
||||
Number of r's in the word strawberry, 3
|
||||
""",
|
||||
expected_output="append to qa_pairs.csv file with questions and answers and move to next task",
|
||||
agent=qa_generator,
|
||||
name="generate_task",
|
||||
is_start=True,
|
||||
next_tasks=["evaluate_total_questions"],
|
||||
task_type="decision",
|
||||
condition={
|
||||
"more": "generate_task",
|
||||
"done": "evaluate_total_questions"
|
||||
}
|
||||
)
|
||||
|
||||
evaluate_total_questions_task = Task(
|
||||
description="Evaluate the total number of questions in qa_pairs.csv file is 1",
|
||||
expected_output="Total number of questions in qa_pairs.csv file",
|
||||
agent=total_questions_evaluator,
|
||||
task_type="decision",
|
||||
name="evaluate_total_questions",
|
||||
condition={
|
||||
"more": "generate_task",
|
||||
"done": "generate_cot"
|
||||
}
|
||||
)
|
||||
|
||||
generate_cot_task = Task(
|
||||
name="generate_cot",
|
||||
description="""Generate chain of thought solutions for each question in the input file.
|
||||
Save to cot_solutions.csv file
|
||||
Don't generate chain of thought solutions again after receiving the response from Tool Call
|
||||
After calling the tool, respond with a JSON object:
|
||||
{
|
||||
"response": "done",
|
||||
"decision": "done"
|
||||
}
|
||||
""",
|
||||
expected_output="done",
|
||||
agent=cot_generator,
|
||||
input_file="qa_pairs.csv",
|
||||
task_type="loop",
|
||||
next_tasks=["upload_to_huggingface"],
|
||||
condition={
|
||||
"done": ["upload_to_huggingface"],
|
||||
"exit": [],
|
||||
},
|
||||
output_pydantic=DecisionModel # Use Pydantic model for output validation
|
||||
)
|
||||
|
||||
upload_to_huggingface_task = Task(
|
||||
name="upload_to_huggingface",
|
||||
description="""Upload to Huggingface:
|
||||
1. Save to cot_solutions.csv
|
||||
2. Upload to mervinpraison/cot-dataset""",
|
||||
expected_output="Dataset published successfully",
|
||||
agent=upload_to_huggingface,
|
||||
tools=[cot_upload_to_huggingface]
|
||||
)
|
||||
|
||||
# Initialize workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[qa_generator, total_questions_evaluator, cot_generator, upload_to_huggingface],
|
||||
tasks=[generate_task, evaluate_total_questions_task, generate_cot_task, upload_to_huggingface_task],
|
||||
process="workflow",
|
||||
max_iter=30,
|
||||
verbose=False
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run the application">
|
||||
Execute the Python script to start generating chain-of-thought data:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Question Generation" icon="question">
|
||||
Create challenging math and logic questions with answers.
|
||||
</Card>
|
||||
<Card title="Question Evaluation" icon="check-double">
|
||||
Evaluate and validate generated questions for quality.
|
||||
</Card>
|
||||
<Card title="CoT Solutions" icon="diagram-project">
|
||||
Generate detailed chain-of-thought solutions for each question.
|
||||
</Card>
|
||||
<Card title="Data Management" icon="database">
|
||||
Save and manage generated data in structured formats.
|
||||
</Card>
|
||||
<Card title="HuggingFace Integration" icon="cloud-arrow-up">
|
||||
Upload datasets directly to HuggingFace for sharing.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Understanding the Workflow
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Key Components">
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Question Generator" icon="robot">
|
||||
Creates unique math and logic questions with answers. Uses `write_csv` and `count_questions` tools.
|
||||
</Card>
|
||||
<Card title="Questions Evaluator" icon="magnifying-glass-chart">
|
||||
Validates the total number of generated questions. Uses `count_questions` tool.
|
||||
</Card>
|
||||
<Card title="CoT Generator" icon="diagram-project">
|
||||
Produces detailed step-by-step solutions. Uses `cot_save` tool for solution management.
|
||||
</Card>
|
||||
<Card title="HuggingFace Uploader" icon="cloud-arrow-up">
|
||||
Publishes datasets to HuggingFace. Uses `cot_upload_to_huggingface` tool.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Types and Flow Control">
|
||||
<Tabs>
|
||||
<Tab title="Decision Tasks">
|
||||
Used in question generation and evaluation phases.
|
||||
|
||||
```python Decision Task Example
|
||||
generate_task = Task(
|
||||
task_type="decision",
|
||||
condition={
|
||||
"more": "generate_task",
|
||||
"done": "evaluate_total_questions"
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
<Note>
|
||||
Conditions determine whether to continue generating or move forward. The task can loop back to itself or proceed to the next task.
|
||||
</Note>
|
||||
</Tab>
|
||||
<Tab title="Loop Tasks">
|
||||
Used in Chain-of-Thought generation phase.
|
||||
|
||||
```python Loop Task Example
|
||||
generate_cot_task = Task(
|
||||
task_type="loop",
|
||||
input_file="qa_pairs.csv",
|
||||
output_pydantic=DecisionModel
|
||||
)
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Always use Pydantic models for output validation in loop tasks to ensure data consistency.
|
||||
</Warning>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Info>
|
||||
Each task type serves a specific purpose in the workflow:
|
||||
- **Decision Tasks**: Control flow and branching logic
|
||||
- **Loop Tasks**: Process data iteratively with validation
|
||||
</Info>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Introduction" icon="book" href="/introduction">
|
||||
Learn more about PraisonAI and its core concepts
|
||||
</Card>
|
||||
<Card title="Quick Start" icon="bolt" href="/quickstart">
|
||||
Get started with the basics of PraisonAI
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: "Image Generation AI Agents"
|
||||
sidebarTitle: "Image Generation"
|
||||
description: "Generate high-quality images using PraisonAI Image Agents with both synchronous and asynchronous capabilities."
|
||||
icon: "image"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Start] --> Process[Image Description]
|
||||
Process --> Agent[Image Agent]
|
||||
Agent --> Out[Image URL]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Process fill:#2E8B57,color:#fff
|
||||
style Agent fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
Image Generation in PraisonAI allows you to create high-quality images using natural language descriptions. The Image Agent supports both synchronous and asynchronous operations, making it flexible for various use cases.
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package with LLM support:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
</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 Agent">
|
||||
Create a new file `image_gen.py` with the basic setup:
|
||||
```python
|
||||
from praisonaiagents.agent.image_agent import ImageAgent
|
||||
|
||||
# Create an image agent
|
||||
agent = ImageAgent(
|
||||
llm="dall-e-3",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Generate an image
|
||||
result = agent.chat("A cute baby sea otter playing with a laptop")
|
||||
print("Image generation result:", result)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package with LLM support:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
</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 Async Agent">
|
||||
Create a new file `image_gen_async.py` with the async setup:
|
||||
```python
|
||||
import asyncio
|
||||
from praisonaiagents import ImageAgent
|
||||
|
||||
async def main():
|
||||
agent = ImageAgent(
|
||||
name="ImageCreator",
|
||||
llm="dall-e-3",
|
||||
style="natural"
|
||||
)
|
||||
|
||||
result = await agent.achat("A cute baby sea otter playing with a laptop")
|
||||
print(f"Image generation result: {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="DALL-E Integration" icon="image">
|
||||
Seamless integration with DALL-E for high-quality image generation.
|
||||
</Card>
|
||||
<Card title="Async Support" icon="bolt">
|
||||
Asynchronous operations for better performance in concurrent environments.
|
||||
</Card>
|
||||
<Card title="Natural Style" icon="paintbrush">
|
||||
Generate images with natural, realistic styling options.
|
||||
</Card>
|
||||
<Card title="Verbose Mode" icon="message">
|
||||
Detailed output logging for better debugging and monitoring.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Agents Overview" icon="robot" href="/agents">
|
||||
Learn more about PraisonAI Agents and their capabilities
|
||||
</Card>
|
||||
<Card title="API Reference" icon="code" href="/api-reference">
|
||||
View the complete API documentation
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,137 @@
|
||||
---
|
||||
title: "Reasoning Extract Agents"
|
||||
description: "Learn how to create AI agents that can perform step-by-step reasoning and extract information"
|
||||
icon: "brain-circuit"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> RA[("Reasoning Agent")]
|
||||
RA --> Steps[Reasoning Steps]
|
||||
Steps --> SA[("Small Agent")]
|
||||
SA --> Out[Output]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style RA fill:#2E8B57,color:#fff,shape:circle
|
||||
style Steps fill:#4169E1,color:#fff
|
||||
style SA fill:#2E8B57,color:#fff,shape:circle
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
A workflow where a reasoning agent breaks down complex problems into steps, followed by a smaller agent that processes these steps to provide concise answers.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install required packages:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
|
||||
<Note>
|
||||
praisonaiagents[llm] includes all necessary dependencies for reasoning agents
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Configure your API key:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key_here
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create File">
|
||||
Create a new file called `app.py` and add the following code:
|
||||
</Step>
|
||||
|
||||
<Step title="Run Application">
|
||||
Execute the script:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Code
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
reasoning_agent = Agent(
|
||||
role="Helpful Assistant",
|
||||
reasoning_steps=True,
|
||||
llm="deepseek/deepseek-reasoner"
|
||||
)
|
||||
|
||||
small_agent = Agent(
|
||||
role="Helpful Assistant",
|
||||
llm="gpt-3.5-turbo"
|
||||
)
|
||||
|
||||
reasoning_task = Task(
|
||||
description="How many r's in the word 'Strawberry'?",
|
||||
agent=reasoning_agent
|
||||
)
|
||||
|
||||
small_task = Task(
|
||||
description="With the provided reasoning tell me how many r's in the word 'Strawberry'?",
|
||||
agent=small_agent
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[reasoning_agent, small_agent],
|
||||
tasks=[reasoning_task, small_task]
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Step-by-Step Reasoning" icon="list-check">
|
||||
Break down complex problems into logical steps.
|
||||
</Card>
|
||||
<Card title="Multi-Agent Collaboration" icon="users">
|
||||
Combine reasoning and processing agents.
|
||||
</Card>
|
||||
<Card title="Flexible Models" icon="arrows-split-up-and-left">
|
||||
Use different models for reasoning and processing.
|
||||
</Card>
|
||||
<Card title="Task Chaining" icon="link">
|
||||
Connect reasoning output to processing tasks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Understanding Reasoning Agents
|
||||
|
||||
<Card title="What are Reasoning Agents?" icon="question">
|
||||
Reasoning agents enable:
|
||||
- Detailed step-by-step analysis
|
||||
- Logical problem decomposition
|
||||
- Clear reasoning paths
|
||||
- Enhanced decision making
|
||||
</Card>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Reasoning Issues" icon="triangle-exclamation">
|
||||
If reasoning steps aren't clear:
|
||||
- Check reasoning_steps parameter
|
||||
- Verify model compatibility
|
||||
- Review task descriptions
|
||||
</Card>
|
||||
|
||||
<Card title="Agent Communication" icon="messages">
|
||||
If agents aren't coordinating:
|
||||
- Ensure task order is correct
|
||||
- Check task dependencies
|
||||
- Verify agent configurations
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
The reasoning agent uses a specialized model (deepseek-reasoner) optimized for step-by-step analysis, while the small agent can use a more general-purpose model for processing the reasoning output.
|
||||
</Note>
|
||||
+442
-98
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Praison AI"
|
||||
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"
|
||||
description: "PraisonAI is a production-ready Multi-AI Agents framework with self-reflection, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. By integrating PraisonAI Agents, AutoGen, and CrewAI into a low-code solution, it streamlines the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration."
|
||||
icon: "house"
|
||||
openGraph:
|
||||
url: "/"
|
||||
@@ -66,24 +66,53 @@ seo:
|
||||
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
|
||||
## Install
|
||||
|
||||
<Tabs>
|
||||
<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 Single Agent
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(instructions="Your are a helpful AI assistant")
|
||||
agent.start("Write a movie script about a robot in Mars")
|
||||
```
|
||||
|
||||
```python Multi Agents
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
|
||||
research_agent = Agent(instructions="Research about AI")
|
||||
summarise_agent = Agent(instructions="Summarise research agent's findings")
|
||||
|
||||
agents = PraisonAIAgents(agents=[research_agent, summarise_agent])
|
||||
agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<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.
|
||||
@@ -109,11 +138,11 @@ seo:
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="Code">
|
||||
<Tab title="JavaScript">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
npm install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
@@ -122,102 +151,390 @@ seo:
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.py` file
|
||||
Create `app.js` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```python Basic
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
```javascript Single Agent
|
||||
const { Agent } = require('praisonai');
|
||||
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
|
||||
agent.start('Write a movie script about a robot in Mars');
|
||||
```
|
||||
|
||||
# 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"
|
||||
)
|
||||
```javascript Multi Agents
|
||||
const { Agent, PraisonAIAgents } = require('praisonai');
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
const researchAgent = new Agent({ instructions: 'Research about AI' });
|
||||
const summariseAgent = new Agent({ instructions: 'Summarise research agent\'s findings' });
|
||||
|
||||
# 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()
|
||||
```
|
||||
const agents = new PraisonAIAgents({ agents: [researchAgent, summariseAgent] });
|
||||
agents.start();
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
python app.py
|
||||
node app.js
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## AI Agents Flow
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[ ]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
end
|
||||
|
||||
subgraph Agent2[ ]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
end
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Start,Output,Task1,Task2 input
|
||||
class Process,AgentIcon1,AgentIcon2 process
|
||||
class Tools1,Tools2 tools
|
||||
class Agent1,Agent2 transparent
|
||||
```
|
||||
|
||||
## AI Agents with Tools
|
||||
|
||||
Create AI agents that can use tools to interact with external systems and perform actions.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Tools
|
||||
direction TB
|
||||
T3[Internet Search]
|
||||
T1[Code Execution]
|
||||
T2[Formatting]
|
||||
end
|
||||
|
||||
Input[Input] ---> Agents
|
||||
subgraph Agents
|
||||
direction LR
|
||||
A1[Agent 1]
|
||||
A2[Agent 2]
|
||||
A3[Agent 3]
|
||||
end
|
||||
Agents ---> Output[Output]
|
||||
|
||||
T3 --> A1
|
||||
T1 --> A2
|
||||
T2 --> A3
|
||||
|
||||
style Tools fill:#189AB4,color:#fff
|
||||
style Agents fill:#8B0000,color:#fff
|
||||
style Input fill:#8B0000,color:#fff
|
||||
style Output fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## AI Agents with Memory
|
||||
|
||||
Create AI agents with memory capabilities for maintaining context and information across tasks.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Memory
|
||||
direction TB
|
||||
STM[Short Term]
|
||||
LTM[Long Term]
|
||||
end
|
||||
|
||||
subgraph Store
|
||||
direction TB
|
||||
DB[(Vector DB)]
|
||||
end
|
||||
|
||||
Input[Input] ---> Agents
|
||||
subgraph Agents
|
||||
direction LR
|
||||
A1[Agent 1]
|
||||
A2[Agent 2]
|
||||
A3[Agent 3]
|
||||
end
|
||||
Agents ---> Output[Output]
|
||||
|
||||
Memory <--> Store
|
||||
Store <--> A1
|
||||
Store <--> A2
|
||||
Store <--> A3
|
||||
|
||||
style Memory fill:#189AB4,color:#fff
|
||||
style Store fill:#2E8B57,color:#fff
|
||||
style Agents fill:#8B0000,color:#fff
|
||||
style Input fill:#8B0000,color:#fff
|
||||
style Output fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## AI Agents with Different Processes
|
||||
|
||||
### Sequential Process
|
||||
|
||||
The simplest form of task execution where tasks are performed one after another.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Input[Input] --> A1
|
||||
subgraph Agents
|
||||
direction LR
|
||||
A1[Agent 1] --> A2[Agent 2] --> A3[Agent 3]
|
||||
end
|
||||
A3 --> Output[Output]
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Input,Output input
|
||||
class A1,A2,A3 process
|
||||
class Agents transparent
|
||||
```
|
||||
|
||||
### Hierarchical Process
|
||||
|
||||
Uses a manager agent to coordinate task execution and agent assignments.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Input[Input] --> Manager
|
||||
|
||||
subgraph Agents
|
||||
Manager[Manager Agent]
|
||||
|
||||
subgraph Workers
|
||||
direction LR
|
||||
W1[Worker 1]
|
||||
W2[Worker 2]
|
||||
W3[Worker 3]
|
||||
end
|
||||
|
||||
Manager --> W1
|
||||
Manager --> W2
|
||||
Manager --> W3
|
||||
end
|
||||
|
||||
W1 --> Manager
|
||||
W2 --> Manager
|
||||
W3 --> Manager
|
||||
Manager --> Output[Output]
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Input,Output input
|
||||
class Manager,W1,W2,W3 process
|
||||
class Agents,Workers transparent
|
||||
```
|
||||
|
||||
### Workflow Process
|
||||
|
||||
Advanced process type supporting complex task relationships and conditional execution.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Input[Input] --> Start
|
||||
|
||||
subgraph Workflow
|
||||
direction LR
|
||||
Start[Start] --> C1{Condition}
|
||||
C1 --> |Yes| A1[Agent 1]
|
||||
C1 --> |No| A2[Agent 2]
|
||||
A1 --> Join
|
||||
A2 --> Join
|
||||
Join --> A3[Agent 3]
|
||||
end
|
||||
|
||||
A3 --> Output[Output]
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef decision fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Input,Output input
|
||||
class Start,A1,A2,A3,Join process
|
||||
class C1 decision
|
||||
class Workflow transparent
|
||||
```
|
||||
|
||||
#### Agentic Routing Workflow
|
||||
|
||||
Create AI agents that can dynamically route tasks to specialized LLM instances.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> Router[LLM Call Router]
|
||||
Router --> LLM1[LLM Call 1]
|
||||
Router --> LLM2[LLM Call 2]
|
||||
Router --> LLM3[LLM Call 3]
|
||||
LLM1 --> Out[Out]
|
||||
LLM2 --> Out
|
||||
LLM3 --> Out
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Router fill:#2E8B57,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Orchestrator Worker
|
||||
|
||||
Create AI agents that orchestrate and distribute tasks among specialized workers.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> Router[LLM Call Router]
|
||||
Router --> LLM1[LLM Call 1]
|
||||
Router --> LLM2[LLM Call 2]
|
||||
Router --> LLM3[LLM Call 3]
|
||||
LLM1 --> Synthesizer[Synthesizer]
|
||||
LLM2 --> Synthesizer
|
||||
LLM3 --> Synthesizer
|
||||
Synthesizer --> Out[Out]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Router fill:#2E8B57,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Synthesizer fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Autonomous Workflow
|
||||
|
||||
Create AI agents that can autonomously monitor, act, and adapt based on environment feedback.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Human[Human] <--> LLM[LLM Call]
|
||||
LLM -->|ACTION| Environment[Environment]
|
||||
Environment -->|FEEDBACK| LLM
|
||||
LLM --> Stop[Stop]
|
||||
|
||||
style Human fill:#8B0000,color:#fff
|
||||
style LLM fill:#2E8B57,color:#fff
|
||||
style Environment fill:#8B0000,color:#fff
|
||||
style Stop fill:#333,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Parallelization
|
||||
|
||||
Create AI agents that can execute tasks in parallel for improved performance.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> LLM2[LLM Call 2]
|
||||
In --> LLM1[LLM Call 1]
|
||||
In --> LLM3[LLM Call 3]
|
||||
LLM1 --> Aggregator[Aggregator]
|
||||
LLM2 --> Aggregator
|
||||
LLM3 --> Aggregator
|
||||
Aggregator --> Out[Out]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Aggregator fill:#fff,color:#000
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Prompt Chaining
|
||||
|
||||
Create AI agents with sequential prompt chaining for complex workflows.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> LLM1[LLM Call 1] --> Gate{Gate}
|
||||
Gate -->|Pass| LLM2[LLM Call 2] -->|Output 2| LLM3[LLM Call 3] --> Out[Out]
|
||||
Gate -->|Fail| Exit[Exit]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style LLM1 fill:#2E8B57,color:#fff
|
||||
style LLM2 fill:#2E8B57,color:#fff
|
||||
style LLM3 fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
style Exit fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Agentic Evaluator Optimizer
|
||||
|
||||
Create AI agents that can generate and optimize solutions through iterative feedback.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[In] --> Generator[LLM Call Generator]
|
||||
Generator -->|SOLUTION| Evaluator[LLM Call Evaluator] -->|ACCEPTED| Out[Out]
|
||||
Evaluator -->|REJECTED + FEEDBACK| Generator
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Generator fill:#2E8B57,color:#fff
|
||||
style Evaluator fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
#### Repetitive Agents
|
||||
|
||||
Create AI agents that can efficiently handle repetitive tasks through automated loops.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> LoopAgent[("Looping Agent")]
|
||||
LoopAgent --> Task[Task]
|
||||
Task --> |Next iteration| LoopAgent
|
||||
Task --> |Done| Out[Output]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style LoopAgent fill:#2E8B57,color:#fff,shape:circle
|
||||
style Task fill:#2E8B57,color:#fff
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
<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>
|
||||
|
||||
## Integration Options
|
||||
|
||||
<AccordionGroup>
|
||||
@@ -338,4 +655,31 @@ seo:
|
||||
<div className="hover:opacity-80 transition-opacity">
|
||||
<img src="https://img.shields.io/github/forks/MervinPraison/PraisonAI?style=social" alt="GitHub Forks" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Video Tutorials
|
||||
|
||||
| Topic | Video |
|
||||
|-------|--------|
|
||||
| AI Agents with Self Reflection | [](https://www.youtube.com/watch?v=vLXobEN2Vc8) |
|
||||
| Reasoning Data Generating Agent | [](https://www.youtube.com/watch?v=fUT332Y2zA8) |
|
||||
| AI Agents with Reasoning | [](https://www.youtube.com/watch?v=KNDVWGN3TpM) |
|
||||
| Multimodal AI Agents | [](https://www.youtube.com/watch?v=hjAWmUT1qqY) |
|
||||
| AI Agents Workflow | [](https://www.youtube.com/watch?v=yWTH44QPl2A) |
|
||||
| Async AI Agents | [](https://www.youtube.com/watch?v=VhVQfgo00LE) |
|
||||
| Mini AI Agents | [](https://www.youtube.com/watch?v=OkvYp5aAGSg) |
|
||||
| AI Agents with Memory | [](https://www.youtube.com/watch?v=1hVfVxvPnnQ) |
|
||||
| Repetitive Agents | [](https://www.youtube.com/watch?v=dAYGxsjDOPg) |
|
||||
| Introduction | [](https://www.youtube.com/watch?v=Fn1lQjC0GO0) |
|
||||
| Tools Overview | [](https://www.youtube.com/watch?v=XaQRgRpV7jo) |
|
||||
| Custom Tools | [](https://www.youtube.com/watch?v=JSU2Rndh06c) |
|
||||
| Firecrawl Integration | [](https://www.youtube.com/watch?v=UoqUDcLcOYo) |
|
||||
| User Interface | [](https://www.youtube.com/watch?v=tg-ZjNl3OCg) |
|
||||
| Crawl4AI Integration | [](https://www.youtube.com/watch?v=KAvuVUh0XU8) |
|
||||
| Chat Interface | [](https://www.youtube.com/watch?v=sw3uDqn2h1Y) |
|
||||
| Code Interface | [](https://www.youtube.com/watch?v=_5jQayO-MQY) |
|
||||
| Mem0 Integration | [](https://www.youtube.com/watch?v=KIGSgRxf1cY) |
|
||||
| Training | [](https://www.youtube.com/watch?v=aLawE8kwCrI) |
|
||||
| Realtime Voice Interface | [](https://www.youtube.com/watch?v=frRHfevTCSw) |
|
||||
| Call Interface | [](https://www.youtube.com/watch?v=m1cwrUG2iAk) |
|
||||
| Reasoning Extract Agents | [](https://www.youtube.com/watch?v=2PPamsADjJA) |
|
||||
@@ -11,6 +11,9 @@ pip install praisonaiagents
|
||||
```bash No Code
|
||||
pip install praisonai
|
||||
```
|
||||
```bash JavaScript
|
||||
npm install praisonai
|
||||
```
|
||||
</RequestExample>
|
||||
|
||||
<Note>
|
||||
@@ -90,6 +93,22 @@ Follow these steps to set up PraisonAI in your development environment.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="JavaScript">
|
||||
<Steps>
|
||||
<Step title="Install PraisonAI">
|
||||
Install the PraisonAI package:
|
||||
```bash
|
||||
npm install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
Set your OpenAI API key as an environment variable in your terminal:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys)
|
||||
|
||||
+141
-121
@@ -89,143 +89,163 @@ graph LR
|
||||
## Getting Started is Easy
|
||||
<Tabs>
|
||||
<Tab title="Code">
|
||||
<Steps>
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install PraisonAI">
|
||||
Install the core package:
|
||||
```bash Terminal
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys).
|
||||
Use other LLM providers like Ollama, Anthropic, Groq, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</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)
|
||||
Use other LLM providers like Ollama, Anthropic, Groq, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</Step>
|
||||
<Step title="Create Agents">
|
||||
Create `app.py`:
|
||||
<CodeGroup>
|
||||
```python Single Agent
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create `app.py`:
|
||||
<CodeGroup>
|
||||
```python Single Agent
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
# Create a simple agent
|
||||
summarise_agent = Agent(instructions="Summarise Photosynthesis")
|
||||
|
||||
# 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"
|
||||
)
|
||||
# Run the agent
|
||||
agents = PraisonAIAgents(agents=[summarise_agent])
|
||||
agents.start()
|
||||
```
|
||||
|
||||
# Define a task
|
||||
task = Task(
|
||||
name="research_task",
|
||||
description="Analyze 2024's AI advancements",
|
||||
expected_output="A detailed report",
|
||||
agent=researcher
|
||||
)
|
||||
```python Multiple Agents
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
|
||||
# Run the agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
verbose=False
|
||||
)
|
||||
# Create agents with specific roles
|
||||
diet_agent = Agent(
|
||||
instructions="Give me 5 healthy food recipes",
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
```
|
||||
blog_agent = Agent(
|
||||
instructions="Write a blog post about the food recipes",
|
||||
)
|
||||
|
||||
```python Multiple Agents
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
# Run multiple agents
|
||||
agents = PraisonAIAgents(agents=[diet_agent, blog_agent])
|
||||
agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
# 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
|
||||
)
|
||||
<Step title="Run Agents">
|
||||
Execute your script:
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
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="Start Agents">
|
||||
Execute your script:
|
||||
```bash Terminal
|
||||
python app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
You'll see:
|
||||
- Agent initialization
|
||||
- Task execution progress
|
||||
- Final results
|
||||
|
||||
<Tip>
|
||||
You have successfully CreatedAI Agents and made them work for you!
|
||||
</Tip>
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="No Code">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install the No Code PraisonAI Package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install PraisonAI">
|
||||
Install the PraisonAI package:
|
||||
```bash
|
||||
pip install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your OpenAI API key as an environment variable in your terminal:
|
||||
```bash Terminal
|
||||
export OPENAI_API_KEY=your_openai_key
|
||||
```
|
||||
Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys)
|
||||
Use other LLM providers like Ollama, Anthropic, Groq, Google, etc. Please refer to the [Models](/models) for more information.
|
||||
</Step>
|
||||
<Step title="Create Config">
|
||||
Create `agents.yaml`:
|
||||
|
||||
<Step title="Start AutoAgents">
|
||||
Run your AutoAgents:
|
||||
```bash
|
||||
praisonai --auto "Create a movie script about a robot in Mars"
|
||||
```
|
||||
</Step>
|
||||
<CodeGroup>
|
||||
```yaml Single Agent
|
||||
roles:
|
||||
summarise_agent:
|
||||
instructions: Summarise Photosynthesis
|
||||
```
|
||||
|
||||
```yaml Multiple Agents
|
||||
roles:
|
||||
diet_agent:
|
||||
instructions: Give me 5 healthy food recipes
|
||||
blog_agent:
|
||||
instructions: Write a blog post about the food recipes
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
You can automatically create `agents.yaml` using:
|
||||
```bash
|
||||
praisonai --init "your task description"
|
||||
```
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agents">
|
||||
Execute your config:
|
||||
```bash
|
||||
praisonai agents.yaml
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="JavaScript">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
npm install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.js` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```javascript Single Agent
|
||||
const { Agent } = require('praisonai');
|
||||
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
|
||||
agent.start('Write a movie script about a robot in Mars');
|
||||
```
|
||||
|
||||
```javascript Multi Agents
|
||||
const { Agent, PraisonAIAgents } = require('praisonai');
|
||||
|
||||
const researchAgent = new Agent({ instructions: 'Research about AI' });
|
||||
const summariseAgent = new Agent({ instructions: 'Summarise research agent\'s findings' });
|
||||
|
||||
const agents = new PraisonAIAgents({ agents: [researchAgent, summariseAgent] });
|
||||
agents.start();
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "Development Setup"
|
||||
sidebarTitle: "Development"
|
||||
description: "Set up your development environment for PraisonAI JavaScript framework"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
## Development Setup
|
||||
|
||||
<Steps>
|
||||
<Step title="Clone Repository">
|
||||
```bash
|
||||
git clone https://github.com/MervinPraison/PraisonAI.git
|
||||
cd src/praisonai-ts
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install Dependencies">
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Build Package">
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Package Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── agent/ # Agent-related interfaces and implementations
|
||||
├── task/ # Task management and execution
|
||||
├── utils/ # Utility functions and helpers
|
||||
└── types/ # TypeScript type definitions
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
---
|
||||
title: "JavaScript AI Agents Framework"
|
||||
sidebarTitle: "JavaScript Agents"
|
||||
description: "A production-ready Multi AI Agents framework for JavaScript"
|
||||
icon: "js"
|
||||
---
|
||||
|
||||
PraisonAI is a production-ready Multi AI Agents framework for JavaScript, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. It provides a low-code solution to streamline the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[ ]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
end
|
||||
|
||||
subgraph Agent2[ ]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
end
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Start,Output,Task1,Task2 input
|
||||
class Process,AgentIcon1,AgentIcon2 process
|
||||
class Tools1,Tools2 tools
|
||||
class Agent1,Agent2 transparent
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<Tab title="JavaScript">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install praisonai
|
||||
```
|
||||
```bash yarn
|
||||
yarn add praisonai
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.js` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```javascript Single Agent
|
||||
const { Agent } = require('praisonai');
|
||||
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
|
||||
agent.start('Write a movie script about a robot in Mars');
|
||||
```
|
||||
|
||||
```javascript Multi Agents
|
||||
const { Agent, PraisonAIAgents } = require('praisonai');
|
||||
|
||||
const researchAgent = new Agent({ instructions: 'Research about AI' });
|
||||
const summariseAgent = new Agent({ instructions: 'Summarise research agent\'s findings' });
|
||||
|
||||
const agents = new PraisonAIAgents({ agents: [researchAgent, summariseAgent] });
|
||||
agents.start();
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
## Usage Examples
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Single Agent Example" icon="user" defaultOpen>
|
||||
Create and run a single agent to perform a specific task:
|
||||
|
||||
```javascript
|
||||
const { Agent } = require('praisonai');
|
||||
|
||||
// Create a simple science explainer agent
|
||||
const agent = new Agent({
|
||||
instructions: "You are a science expert who explains complex phenomena in simple terms.",
|
||||
name: "ScienceExplainer",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Ask a question
|
||||
agent.start("Why is the sky blue?")
|
||||
.then(response => {
|
||||
console.log('\nExplanation:');
|
||||
console.log(response);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Multi-Agent Example" icon="users" defaultOpen>
|
||||
Create and run multiple agents working together:
|
||||
|
||||
```javascript
|
||||
const { PraisonAIAgents, Agent } = require('praisonai');
|
||||
|
||||
// Create a story agent and a summary agent
|
||||
const storyAgent = new Agent({
|
||||
instructions: "You are a creative storyteller. Create engaging stories.",
|
||||
name: "Storyteller"
|
||||
});
|
||||
|
||||
const summaryAgent = new Agent({
|
||||
instructions: "You summarize stories into brief, engaging summaries.",
|
||||
name: "Summarizer"
|
||||
});
|
||||
|
||||
// Create multi-agent system
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [storyAgent, summaryAgent],
|
||||
tasks: [
|
||||
"Create a short story about a magical forest",
|
||||
"Summarize the story in 2 sentences"
|
||||
]
|
||||
});
|
||||
|
||||
// Run the agents
|
||||
agents.start()
|
||||
.then(responses => {
|
||||
console.log('\nStory:');
|
||||
console.log(responses[0]);
|
||||
console.log('\nSummary:');
|
||||
console.log(responses[1]);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task-Based Agent Example" icon="list-check" defaultOpen>
|
||||
Create agents with specific tasks and dependencies:
|
||||
|
||||
```javascript
|
||||
const { Agent, Task } = require('praisonai');
|
||||
|
||||
// Create a task-based agent
|
||||
const agent = new Agent({
|
||||
name: "TaskMaster",
|
||||
role: "Assistant",
|
||||
goal: "Complete tasks efficiently",
|
||||
backstory: "You are an AI assistant that helps complete tasks step by step."
|
||||
});
|
||||
|
||||
// Create a task with dependencies
|
||||
const mainTask = new Task({
|
||||
name: "Write Blog Post",
|
||||
description: "Write a blog post about artificial intelligence",
|
||||
expected_output: "A complete blog post",
|
||||
dependencies: []
|
||||
});
|
||||
|
||||
// Execute the task
|
||||
agent.execute(mainTask)
|
||||
.then(response => {
|
||||
console.log('\nBlog Post:');
|
||||
console.log(response);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Running the Examples
|
||||
|
||||
<Steps>
|
||||
<Step title="Set Environment Variables">
|
||||
```bash
|
||||
export OPENAI_API_KEY='your-api-key'
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Example File">
|
||||
Create a new JavaScript file (e.g., `app.js`) with any of the above examples.
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Example">
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
@@ -0,0 +1,251 @@
|
||||
---
|
||||
title: "Node.js AI Agents Framework"
|
||||
sidebarTitle: "Node.js Agents"
|
||||
description: "A production-ready Multi AI Agents framework for Node.js"
|
||||
icon: "node-js"
|
||||
---
|
||||
|
||||
PraisonAI is a production-ready Multi AI Agents framework for Node.js, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. It provides a low-code solution to streamline the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[ ]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
end
|
||||
|
||||
subgraph Agent2[ ]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
end
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Start,Output,Task1,Task2 input
|
||||
class Process,AgentIcon1,AgentIcon2 process
|
||||
class Tools1,Tools2 tools
|
||||
class Agent1,Agent2 transparent
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Node.js">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install praisonai
|
||||
```
|
||||
```bash yarn
|
||||
yarn add praisonai
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.js` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```javascript Single Agent
|
||||
const { Agent } = require('praisonai');
|
||||
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
|
||||
agent.start('Write a movie script about a robot in Mars');
|
||||
```
|
||||
|
||||
```javascript Multi Agents
|
||||
const { Agent, PraisonAIAgents } = require('praisonai');
|
||||
|
||||
const researchAgent = new Agent({ instructions: 'Research about AI' });
|
||||
const summariseAgent = new Agent({ instructions: 'Summarise research agent\'s findings' });
|
||||
|
||||
const agents = new PraisonAIAgents({ agents: [researchAgent, summariseAgent] });
|
||||
agents.start();
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Single Agent Example" icon="user" defaultOpen>
|
||||
Create and run a single agent to perform a specific task:
|
||||
|
||||
```typescript
|
||||
import { Agent } from 'praisonai';
|
||||
|
||||
// Single agent example - Science Explainer
|
||||
const agent = new Agent({
|
||||
instructions: `You are a science expert who explains complex phenomena in simple terms.
|
||||
Provide clear, accurate, and easy-to-understand explanations.`,
|
||||
name: "ScienceExplainer",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
agent.start("Why is the sky blue?")
|
||||
.then(response => {
|
||||
console.log('\nExplanation:');
|
||||
console.log(response);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Multi-Agent Example" icon="users" defaultOpen>
|
||||
Create and run multiple agents working together:
|
||||
|
||||
```typescript
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
// Create story agent
|
||||
const storyAgent = new Agent({
|
||||
instructions: "You are a storyteller. Write a very short story (2-3 sentences) about a given topic.",
|
||||
name: "StoryAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create summary agent
|
||||
const summaryAgent = new Agent({
|
||||
instructions: "You are an editor. Create a one-sentence summary of the given story.",
|
||||
name: "SummaryAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create and start agents
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [storyAgent, summaryAgent],
|
||||
tasks: [
|
||||
"Write a short story about a cat",
|
||||
"{previous_result}" // This will be replaced with the story
|
||||
],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
agents.start()
|
||||
.then(results => {
|
||||
console.log('\nStory:', results[0]);
|
||||
console.log('\nSummary:', results[1]);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task-Based Agent Example" icon="list-check" defaultOpen>
|
||||
Create agents with specific tasks and dependencies:
|
||||
|
||||
```typescript
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
// Create recipe agent
|
||||
const recipeAgent = new Agent({
|
||||
instructions: `You are a professional chef and nutritionist. Create 5 healthy food recipes that are both nutritious and delicious.
|
||||
Each recipe should include:
|
||||
1. Recipe name
|
||||
2. List of ingredients with quantities
|
||||
3. Step-by-step cooking instructions
|
||||
4. Nutritional information
|
||||
5. Health benefits
|
||||
|
||||
Format your response in markdown.`,
|
||||
name: "RecipeAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create blog agent
|
||||
const blogAgent = new Agent({
|
||||
instructions: `You are a food and health blogger. Write an engaging blog post about the provided recipes.
|
||||
The blog post should:
|
||||
1. Have an engaging title
|
||||
2. Include an introduction about healthy eating
|
||||
3. Discuss each recipe and its unique health benefits
|
||||
4. Include tips for meal planning and preparation
|
||||
5. End with a conclusion encouraging healthy eating habits
|
||||
|
||||
Here are the recipes to write about:
|
||||
{previous_result}
|
||||
|
||||
Format your response in markdown.`,
|
||||
name: "BlogAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create PraisonAIAgents instance with tasks
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [recipeAgent, blogAgent],
|
||||
tasks: [
|
||||
"Create 5 healthy and delicious recipes",
|
||||
"Write a blog post about the recipes"
|
||||
],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Start the agents
|
||||
agents.start()
|
||||
.then(results => {
|
||||
console.log('\nFinal Results:');
|
||||
console.log('\nRecipe Task Results:');
|
||||
console.log(results[0]);
|
||||
console.log('\nBlog Task Results:');
|
||||
console.log(results[1]);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Running the Examples
|
||||
|
||||
<Steps>
|
||||
<Step title="Set Environment Variables">
|
||||
```bash
|
||||
export OPENAI_API_KEY='your-api-key'
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Example File">
|
||||
Create a new TypeScript file (e.g., `app.ts`) with any of the above examples.
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Example">
|
||||
```bash
|
||||
npx ts-node app.ts
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: "TypeScript Async AI Agents"
|
||||
sidebarTitle: "TypeScript Async"
|
||||
description: "A production-ready Multi AI Agents framework for TypeScript Async"
|
||||
icon: "rotate"
|
||||
---
|
||||
|
||||
PraisonAI is a production-ready Multi AI Agents framework for TypeScript Async, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. It provides a low-code solution to streamline the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration.
|
||||
|
||||
## Installation
|
||||
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install praisonai
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add praisonai
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Single Agent Example" icon="user" defaultOpen>
|
||||
Create and run a single agent to perform a specific task:
|
||||
|
||||
```typescript
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create a simple agent (no task specified)
|
||||
const agent = new Agent({
|
||||
name: "BiologyExpert",
|
||||
instructions: "Explain the process of photosynthesis in detail.",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Run the agent
|
||||
const praisonAI = new PraisonAIAgents({
|
||||
agents: [agent],
|
||||
tasks: ["Explain the process of photosynthesis in detail."],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
try {
|
||||
console.log('Starting single agent example...');
|
||||
const results = await praisonAI.start();
|
||||
console.log('\nFinal Results:', results);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Multi-Agent Example" icon="users" defaultOpen>
|
||||
Create and run multiple agents working together:
|
||||
|
||||
```typescript
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create multiple agents with different roles
|
||||
const researchAgent = new Agent({
|
||||
name: "ResearchAgent",
|
||||
instructions: "Research and provide detailed information about renewable energy sources.",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
const summaryAgent = new Agent({
|
||||
name: "SummaryAgent",
|
||||
instructions: "Create a concise summary of the research findings about renewable energy sources. Use {previous_result} as input.",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
const recommendationAgent = new Agent({
|
||||
name: "RecommendationAgent",
|
||||
instructions: "Based on the summary in {previous_result}, provide specific recommendations for implementing renewable energy solutions.",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Run the agents in sequence
|
||||
const praisonAI = new PraisonAIAgents({
|
||||
agents: [researchAgent, summaryAgent, recommendationAgent],
|
||||
tasks: [
|
||||
"Research and analyze current renewable energy technologies and their implementation.",
|
||||
"Summarize the key findings from the research.",
|
||||
"Provide actionable recommendations based on the summary."
|
||||
],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
try {
|
||||
console.log('Starting multi-agent example...');
|
||||
const results = await praisonAI.start();
|
||||
console.log('\nFinal Results:', results);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task-Based Agent Example" icon="list-check" defaultOpen>
|
||||
Create agents with specific tasks and dependencies:
|
||||
|
||||
```typescript
|
||||
import { Agent, Task, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create agents first
|
||||
const dietAgent = new Agent({
|
||||
name: "DietAgent",
|
||||
role: "Nutrition Expert",
|
||||
goal: "Create healthy and delicious recipes",
|
||||
backstory: "You are a certified nutritionist with years of experience in creating balanced meal plans.",
|
||||
verbose: true,
|
||||
instructions: `You are a professional chef and nutritionist. Create 5 healthy food recipes that are both nutritious and delicious.
|
||||
Each recipe should include:
|
||||
1. Recipe name
|
||||
2. List of ingredients with quantities
|
||||
3. Step-by-step cooking instructions
|
||||
4. Nutritional information
|
||||
5. Health benefits
|
||||
|
||||
Format your response in markdown.`
|
||||
});
|
||||
|
||||
const blogAgent = new Agent({
|
||||
name: "BlogAgent",
|
||||
role: "Food Blogger",
|
||||
goal: "Write engaging blog posts about food and recipes",
|
||||
backstory: "You are a successful food blogger known for your ability to make recipes sound delicious and approachable.",
|
||||
verbose: true,
|
||||
instructions: `You are a food and health blogger. Write an engaging blog post about the provided recipes.
|
||||
The blog post should:
|
||||
1. Have an engaging title
|
||||
2. Include an introduction about healthy eating`
|
||||
});
|
||||
|
||||
// Create tasks
|
||||
const createRecipesTask = new Task({
|
||||
name: "Create Recipes",
|
||||
description: "Create 5 healthy and delicious recipes",
|
||||
agent: dietAgent
|
||||
});
|
||||
|
||||
const writeBlogTask = new Task({
|
||||
name: "Write Blog",
|
||||
description: "Write a blog post about the recipes",
|
||||
agent: blogAgent,
|
||||
dependencies: [createRecipesTask] // This task depends on the recipes being created first
|
||||
});
|
||||
|
||||
// Run the tasks
|
||||
const praisonAI = new PraisonAIAgents({
|
||||
tasks: [createRecipesTask, writeBlogTask],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
try {
|
||||
console.log('Starting task-based example...');
|
||||
const results = await praisonAI.start();
|
||||
console.log('\nFinal Results:', results);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Running the Examples
|
||||
|
||||
<Steps>
|
||||
<Step title="Set Environment Variables">
|
||||
```bash
|
||||
export OPENAI_API_KEY='your-api-key'
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Example File">
|
||||
Create a new TypeScript file (e.g., `app.ts`) with any of the above examples.
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Example">
|
||||
```bash
|
||||
npx ts-node app.ts
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
@@ -0,0 +1,266 @@
|
||||
---
|
||||
title: "TypeScript AI Agents Framework"
|
||||
sidebarTitle: "TypeScript Agents"
|
||||
description: "A production-ready Multi AI Agents framework for TypeScript"
|
||||
icon: "scroll"
|
||||
---
|
||||
|
||||
PraisonAI is a production-ready Multi AI Agents framework for TypeScript, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. It provides a low-code solution to streamline the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% Define the main flow
|
||||
Start([▶ Start]) --> Agent1
|
||||
Agent1 --> Process[⚙ Process]
|
||||
Process --> Agent2
|
||||
Agent2 --> Output([✓ Output])
|
||||
Process -.-> Agent1
|
||||
|
||||
%% Define subgraphs for agents and their tasks
|
||||
subgraph Agent1[ ]
|
||||
Task1[📋 Task]
|
||||
AgentIcon1[🤖 AI Agent]
|
||||
Tools1[🔧 Tools]
|
||||
|
||||
Task1 --- AgentIcon1
|
||||
AgentIcon1 --- Tools1
|
||||
end
|
||||
|
||||
subgraph Agent2[ ]
|
||||
Task2[📋 Task]
|
||||
AgentIcon2[🤖 AI Agent]
|
||||
Tools2[🔧 Tools]
|
||||
|
||||
Task2 --- AgentIcon2
|
||||
AgentIcon2 --- Tools2
|
||||
end
|
||||
|
||||
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
|
||||
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
|
||||
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
|
||||
classDef transparent fill:none,stroke:none
|
||||
|
||||
class Start,Output,Task1,Task2 input
|
||||
class Process,AgentIcon1,AgentIcon2 process
|
||||
class Tools1,Tools2 tools
|
||||
class Agent1,Agent2 transparent
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install praisonai
|
||||
```
|
||||
```bash yarn
|
||||
yarn add praisonai
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.ts` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```javascript Single Agent
|
||||
import { Agent } from 'praisonai';
|
||||
|
||||
const agent = new Agent({
|
||||
instructions: `You are a creative writer who writes short stories with emojis.`,
|
||||
name: "StoryWriter"
|
||||
});
|
||||
|
||||
agent.start("Write a story about a time traveler")
|
||||
```
|
||||
|
||||
```javascript Multi Agents
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
const storyAgent = new Agent({
|
||||
instructions: "Generate a very short story (2-3 sentences) about artificial intelligence with emojis.",
|
||||
name: "StoryAgent"
|
||||
});
|
||||
|
||||
const summaryAgent = new Agent({
|
||||
instructions: "Summarize the provided AI story in one sentence with emojis.",
|
||||
name: "SummaryAgent"
|
||||
});
|
||||
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [storyAgent, summaryAgent]
|
||||
});
|
||||
|
||||
agents.start()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
npx ts-node app.ts
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Single Agent Example" icon="user" defaultOpen>
|
||||
Create and run a single agent to perform a specific task:
|
||||
|
||||
```typescript
|
||||
import { Agent } from 'praisonai';
|
||||
|
||||
// Single agent example - Science Explainer
|
||||
const agent = new Agent({
|
||||
instructions: `You are a science expert who explains complex phenomena in simple terms.
|
||||
Provide clear, accurate, and easy-to-understand explanations.`,
|
||||
name: "ScienceExplainer",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
agent.start("Why is the sky blue?")
|
||||
.then(response => {
|
||||
console.log('\nExplanation:');
|
||||
console.log(response);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Multi-Agent Example" icon="users" defaultOpen>
|
||||
Create and run multiple agents working together:
|
||||
|
||||
```typescript
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
// Create story agent
|
||||
const storyAgent = new Agent({
|
||||
instructions: "You are a storyteller. Write a very short story (2-3 sentences) about a given topic.",
|
||||
name: "StoryAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create summary agent
|
||||
const summaryAgent = new Agent({
|
||||
instructions: "You are an editor. Create a one-sentence summary of the given story.",
|
||||
name: "SummaryAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create and start agents
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [storyAgent, summaryAgent],
|
||||
tasks: [
|
||||
"Write a short story about a cat",
|
||||
"{previous_result}" // This will be replaced with the story
|
||||
],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
agents.start()
|
||||
.then(results => {
|
||||
console.log('\nStory:', results[0]);
|
||||
console.log('\nSummary:', results[1]);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task-Based Agent Example" icon="list-check" defaultOpen>
|
||||
Create agents with specific tasks and dependencies:
|
||||
|
||||
```typescript
|
||||
import { Agent, PraisonAIAgents } from 'praisonai';
|
||||
|
||||
// Create recipe agent
|
||||
const recipeAgent = new Agent({
|
||||
instructions: `You are a professional chef and nutritionist. Create 5 healthy food recipes that are both nutritious and delicious.
|
||||
Each recipe should include:
|
||||
1. Recipe name
|
||||
2. List of ingredients with quantities
|
||||
3. Step-by-step cooking instructions
|
||||
4. Nutritional information
|
||||
5. Health benefits
|
||||
|
||||
Format your response in markdown.`,
|
||||
name: "RecipeAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create blog agent
|
||||
const blogAgent = new Agent({
|
||||
instructions: `You are a food and health blogger. Write an engaging blog post about the provided recipes.
|
||||
The blog post should:
|
||||
1. Have an engaging title
|
||||
2. Include an introduction about healthy eating
|
||||
3. Discuss each recipe and its unique health benefits
|
||||
4. Include tips for meal planning and preparation
|
||||
5. End with a conclusion encouraging healthy eating habits
|
||||
|
||||
Here are the recipes to write about:
|
||||
{previous_result}
|
||||
|
||||
Format your response in markdown.`,
|
||||
name: "BlogAgent",
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Create PraisonAIAgents instance with tasks
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [recipeAgent, blogAgent],
|
||||
tasks: [
|
||||
"Create 5 healthy and delicious recipes",
|
||||
"Write a blog post about the recipes"
|
||||
],
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Start the agents
|
||||
agents.start()
|
||||
.then(results => {
|
||||
console.log('\nFinal Results:');
|
||||
console.log('\nRecipe Task Results:');
|
||||
console.log(results[0]);
|
||||
console.log('\nBlog Task Results:');
|
||||
console.log(results[1]);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Running the Examples
|
||||
|
||||
<Steps>
|
||||
<Step title="Set Environment Variables">
|
||||
```bash
|
||||
export OPENAI_API_KEY='your-api-key'
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Example File">
|
||||
Create a new TypeScript file (e.g., `app.ts`) with any of the above examples.
|
||||
</Step>
|
||||
|
||||
<Step title="Run the Example">
|
||||
```bash
|
||||
npx ts-node app.ts
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
+26
-2
@@ -74,6 +74,10 @@
|
||||
{
|
||||
"name": "Tools",
|
||||
"url": "/tools"
|
||||
},
|
||||
{
|
||||
"name": "JS",
|
||||
"url": "/js"
|
||||
}
|
||||
],
|
||||
"navigation": [
|
||||
@@ -115,18 +119,23 @@
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/cli",
|
||||
"features/autoagents",
|
||||
"features/image-generation",
|
||||
"features/selfreflection",
|
||||
"features/rag",
|
||||
"features/reasoning-extract",
|
||||
"features/reasoning",
|
||||
"features/multimodal",
|
||||
"features/langchain",
|
||||
"features/async",
|
||||
"features/mini",
|
||||
"features/generate-reasoning",
|
||||
"features/codeagent",
|
||||
"features/mathagent",
|
||||
"features/structured",
|
||||
"features/callbacks"
|
||||
"features/callbacks",
|
||||
"features/chat-with-pdf"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -141,6 +150,7 @@
|
||||
"models/anthropic",
|
||||
"models/cohere",
|
||||
"models/mistral",
|
||||
"models/deepseek",
|
||||
"models/other"
|
||||
]
|
||||
},
|
||||
@@ -230,6 +240,16 @@
|
||||
"tools/googlecalendar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "JavaScript",
|
||||
"pages": [
|
||||
"js/js",
|
||||
"js/typescript",
|
||||
"js/nodejs",
|
||||
"js/typescript-async",
|
||||
"js/development"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Other Features",
|
||||
"pages": [
|
||||
@@ -250,7 +270,10 @@
|
||||
"pages": [
|
||||
"ui/streamlit",
|
||||
"ui/streamlit/code-analysis-streamlit",
|
||||
"ui/streamlit/hackathon-judge-streamlit"
|
||||
"ui/streamlit/hackathon-judge-streamlit",
|
||||
"ui/streamlit/ollama-streamlit",
|
||||
"ui/streamlit/deepseek-streamlit",
|
||||
"ui/streamlit/gemini-streamlit"
|
||||
]
|
||||
},
|
||||
"ui/ui",
|
||||
@@ -271,6 +294,7 @@
|
||||
"developers/wrapper-tools",
|
||||
"developers/googlecolab",
|
||||
"developers/googlecolab-tools",
|
||||
"developers/local-development",
|
||||
"deploy"
|
||||
]
|
||||
},
|
||||
|
||||
+178
-1
@@ -4,7 +4,184 @@ description: "Overview of supported language models in PraisonAI, including Open
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
## Supported Models for Code
|
||||
# Code
|
||||
|
||||
## Set model by 3 ways
|
||||
|
||||
### 1. OpenAI Compatible Endpoints
|
||||
|
||||
<Note>By Default it uses OPENAI_BASE_URL https://api.openai.com/v1 </Note>
|
||||
Example Groq Implementation:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=groq-api-key
|
||||
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
|
||||
```
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="llama-3.1-8b-instant",
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
```
|
||||
|
||||
### 2. Litellm Compatible model names (eg: gemini/gemini-1.5-flash-8b)
|
||||
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
```
|
||||
|
||||
### 3. Litellm Compatible Configuration
|
||||
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
llm_config = {
|
||||
"model": "gemini/gemini-1.5-flash-latest", # Model name without provider prefix
|
||||
|
||||
# Core settings
|
||||
"temperature": 0.7, # Controls randomness (like temperature)
|
||||
"timeout": 30, # Timeout in seconds
|
||||
"top_p": 0.9, # Nucleus sampling parameter
|
||||
"max_tokens": 1000, # Max tokens in response
|
||||
|
||||
# Advanced parameters
|
||||
"presence_penalty": 0.1, # Penalize repetition of topics (-2.0 to 2.0)
|
||||
"frequency_penalty": 0.1, # Penalize token repetition (-2.0 to 2.0)
|
||||
|
||||
# API settings (optional)
|
||||
"api_key": None, # Your API key (or use environment variable)
|
||||
"base_url": None, # Custom API endpoint if needed
|
||||
|
||||
# Response formatting
|
||||
"response_format": { # Force specific response format
|
||||
"type": "text" # Options: "text", "json_object"
|
||||
},
|
||||
|
||||
# Additional controls
|
||||
"seed": 42, # For reproducible responses
|
||||
"stop_phrases": ["##", "END"], # Custom stop sequences
|
||||
}
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful Assistant."
|
||||
llm=llm_config
|
||||
)
|
||||
agent.start()
|
||||
```
|
||||
|
||||
## Advanced Configuration (Litellm Support)
|
||||
|
||||
<Note>This uses Litellm</Note>
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install required packages:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Setup Environment">
|
||||
Configure environment:
|
||||
```bash
|
||||
export GOOGLE_API_KEY=your-api-key
|
||||
```
|
||||
|
||||
<Note>
|
||||
Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create `app.py`:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Basic
|
||||
# if json_object is supported by the model
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
```
|
||||
|
||||
```python Advanced
|
||||
# if json_object is not supported by the model
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Detailed LLM configuration
|
||||
llm_config = {
|
||||
"model": "gemini/gemini-1.5-flash-latest", # Model name without provider prefix
|
||||
|
||||
# Core settings
|
||||
"temperature": 0.7, # Controls randomness (like temperature)
|
||||
"timeout": 30, # Timeout in seconds
|
||||
"top_p": 0.9, # Nucleus sampling parameter
|
||||
"max_tokens": 1000, # Max tokens in response
|
||||
|
||||
# Advanced parameters
|
||||
"presence_penalty": 0.1, # Penalize repetition of topics (-2.0 to 2.0)
|
||||
"frequency_penalty": 0.1, # Penalize token repetition (-2.0 to 2.0)
|
||||
|
||||
# API settings (optional)
|
||||
"api_key": None, # Your API key (or use environment variable)
|
||||
"base_url": None, # Custom API endpoint if needed
|
||||
|
||||
# Response formatting
|
||||
"response_format": { # Force specific response format
|
||||
"type": "text" # Options: "text", "json_object"
|
||||
},
|
||||
|
||||
# Additional controls
|
||||
"seed": 42, # For reproducible responses
|
||||
"stop_phrases": ["##", "END"], # Custom stop sequences
|
||||
}
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful Assistant specialized in scientific explanations. "
|
||||
"Provide clear, accurate, and engaging responses.",
|
||||
llm=llm_config, # Pass the detailed configuration
|
||||
verbose=True, # Enable detailed output
|
||||
markdown=True, # Format responses in markdown
|
||||
self_reflect=True, # Enable self-reflection
|
||||
max_reflect=3, # Maximum reflection iterations
|
||||
min_reflect=1 # Minimum reflection iterations
|
||||
)
|
||||
|
||||
# Test the agent
|
||||
response = agent.start("Why is the sky blue? Please explain in simple terms.")
|
||||
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Ollama Integration" defaultOpen>
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
---
|
||||
title: "DeepSeek Agents"
|
||||
|
||||
description: "Learn how to use Deepseek models with PraisonAI Agents for various applications."
|
||||
icon: "brain"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> Ollama[("Ollama")]
|
||||
Ollama --> DS[("Deepseek")]
|
||||
DS --> Basic[Basic Agent]
|
||||
DS --> RAG[RAG Agent]
|
||||
DS --> UI[UI Agent]
|
||||
Basic --> Out1[Output]
|
||||
RAG --> Out2[Output]
|
||||
UI --> Out3[Output]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style Ollama fill:#4169E1,color:#fff,shape:circle
|
||||
style DS fill:#2E8B57,color:#fff,shape:circle
|
||||
style Basic fill:#2E8B57,color:#fff
|
||||
style RAG fill:#2E8B57,color:#fff
|
||||
style UI fill:#2E8B57,color:#fff
|
||||
style Out1 fill:#8B0000,color:#fff
|
||||
style Out2 fill:#8B0000,color:#fff
|
||||
style Out3 fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
Learn how to use Deepseek models with PraisonAI Agents through Ollama integration for basic queries, RAG applications, and interactive UI implementations.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Ollama">
|
||||
First, install Ollama on your system:
|
||||
```bash
|
||||
curl -fsSL https://ollama.com/install.sh | sh
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Pull Deepseek Model">
|
||||
Pull the Deepseek model from Ollama:
|
||||
```bash
|
||||
ollama pull deepseek-r1
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install Package">
|
||||
Install PraisonAI Agents:
|
||||
```bash
|
||||
pip install "praisonaiagents[knowledge]" ollama streamlit
|
||||
```
|
||||
|
||||
<Note>
|
||||
Streamlit for UI is optional.
|
||||
Ollama is required for Local RAG Agents.
|
||||
praisonaiagents[knowledge] is for RAG Agents. praisonaiagents is for Basic Agents.
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Set Environment">
|
||||
Set Ollama as your base URL:
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
export OPENAI_API_KEY=fake-key
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Basic Usage
|
||||
|
||||
The simplest way to use Deepseek with PraisonAI Agents:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(instructions="You are helpful Assisant", llm="deepseek-r1")
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
```
|
||||
|
||||
## RAG Implementation
|
||||
|
||||
Use Deepseek with RAG capabilities for knowledge-based interactions:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
agent = Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"], # Indexing
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
agent.start("What is KAG in one line?") # Retrieval
|
||||
```
|
||||
|
||||
## Interactive UI with Streamlit
|
||||
|
||||
Create an interactive chat interface using Streamlit:
|
||||
|
||||
```python
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
def init_agent():
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"],
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
st.title("Knowledge Agent Chat")
|
||||
|
||||
if "agent" not in st.session_state:
|
||||
st.session_state.agent = init_agent()
|
||||
st.session_state.messages = []
|
||||
|
||||
if "messages" in st.session_state:
|
||||
for message in st.session_state.messages:
|
||||
with st.chat_message(message["role"]):
|
||||
st.markdown(message["content"])
|
||||
|
||||
prompt = st.chat_input("Ask a question...")
|
||||
|
||||
if prompt:
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
with st.chat_message("user"):
|
||||
st.markdown(prompt)
|
||||
|
||||
with st.chat_message("assistant"):
|
||||
response = st.session_state.agent.start(prompt)
|
||||
st.markdown(response)
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
```
|
||||
|
||||
## Running the UI
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Streamlit">
|
||||
Install Streamlit if you haven't already:
|
||||
```bash
|
||||
pip install streamlit
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Save and Run">
|
||||
Save the UI code in a file (e.g., `app.py`) and run:
|
||||
```bash
|
||||
streamlit run app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Local Deployment" icon="server">
|
||||
Run Deepseek models locally through Ollama.
|
||||
</Card>
|
||||
<Card title="RAG Capabilities" icon="database">
|
||||
Integrate with vector databases for knowledge retrieval.
|
||||
</Card>
|
||||
<Card title="Interactive UI" icon="desktop">
|
||||
Create chat interfaces with Streamlit integration.
|
||||
</Card>
|
||||
<Card title="Custom Configuration" icon="gear">
|
||||
Configure model parameters and embedding settings.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Ollama Issues" icon="triangle-exclamation">
|
||||
If Ollama isn't working:
|
||||
- Check if Ollama is running
|
||||
- Verify model is downloaded
|
||||
- Check port availability
|
||||
</Card>
|
||||
|
||||
<Card title="Performance Issues" icon="gauge-high">
|
||||
If responses are slow:
|
||||
- Check system resources
|
||||
- Adjust max_tokens
|
||||
- Monitor memory usage
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
For optimal performance, ensure your system meets the minimum requirements for running Deepseek models locally through Ollama.
|
||||
</Note>
|
||||
+165
-7
@@ -1,12 +1,166 @@
|
||||
---
|
||||
title: "Google Gemini"
|
||||
title: "Google Gemini Agents"
|
||||
sidebarTitle: "Google Gemini"
|
||||
description: "Instructions for integrating Google's Gemini models with PraisonAI, including API setup and configuration details"
|
||||
icon: "google"
|
||||
---
|
||||
|
||||
# Add Google Gemini to Praison AI
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> API[("Google API")]
|
||||
API --> Gemini[("Gemini")]
|
||||
Gemini --> Basic[Basic Agent]
|
||||
Gemini --> Multi[Multi-Agents]
|
||||
Gemini --> YAML[No-Code]
|
||||
Basic --> Out1[Output]
|
||||
Multi --> Out2[Output]
|
||||
YAML --> Out3[Output]
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style API fill:#4169E1,color:#fff,shape:circle
|
||||
style Gemini fill:#2E8B57,color:#fff,shape:circle
|
||||
style Basic fill:#2E8B57,color:#fff
|
||||
style Multi fill:#2E8B57,color:#fff
|
||||
style YAML fill:#2E8B57,color:#fff
|
||||
style Out1 fill:#8B0000,color:#fff
|
||||
style Out2 fill:#8B0000,color:#fff
|
||||
style Out3 fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## Code
|
||||
## Prerequisites
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install PraisonAI Agents:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
|
||||
<Note>
|
||||
praisonaiagents[llm] includes all Google Gemini dependencies.
|
||||
For No-Code implementation, also install: pip install langchain-google-genai
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your Gemini API key:
|
||||
```bash
|
||||
export GEMINI_API_KEY=xxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Code">
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Code Implementation
|
||||
|
||||
### Basic Usage
|
||||
|
||||
The simplest way to use Gemini with PraisonAI Agents:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
```
|
||||
|
||||
### Multi-Agent Setup
|
||||
|
||||
Create multiple agents working together:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Why sky is Blue?",
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
)
|
||||
|
||||
agents.start()
|
||||
```
|
||||
|
||||
<Note>
|
||||
This uses Litellm to connect to Google Gemini.
|
||||
</Note>
|
||||
|
||||
## Gemini 2.0 Flash Thinking
|
||||
|
||||
### LLM Configuration
|
||||
```python
|
||||
llm_config = {
|
||||
"model": "gemini/gemini-2.0-flash-thinking-exp-01-21",
|
||||
"response_format": {"type": "text"} # type is text, because json_object is not supported
|
||||
}
|
||||
```
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install required packages:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]"
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Set API Key">
|
||||
Set your Gemini API key:
|
||||
```bash
|
||||
export GEMINI_API_KEY=xxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Code">
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
|
||||
llm_config = {"model": "gemini/gemini-2.0-flash-thinking-exp-01-21","response_format": {"type": "text"}}
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm=llm_config
|
||||
)
|
||||
|
||||
result = agent.start("Why sky is Blue?")
|
||||
print(result)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Alternative Setup
|
||||
|
||||
### Using Environment Variables
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Google Gemini" defaultOpen>
|
||||
@@ -16,16 +170,18 @@ icon: "google"
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
## No Code
|
||||
|
||||
## No-Code Implementation
|
||||
|
||||
### Setup
|
||||
```bash
|
||||
pip install langchain-google-genai
|
||||
```
|
||||
```bash
|
||||
export GOOGLE_API_KEY=xxxxxxxxxx
|
||||
```
|
||||
|
||||
### agents.yaml file
|
||||
### YAML Configuration
|
||||
|
||||
Create an `agents.yaml` file:
|
||||
|
||||
```yaml
|
||||
framework: crewai
|
||||
@@ -48,6 +204,8 @@ roles:
|
||||
- ''
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
| PraisonAI Chat | PraisonAI Code | PraisonAI (Multi-Agents) |
|
||||
| --- | --- | --- |
|
||||
| [Litellm](https://litellm.vercel.app/docs/providers) | [Litellm](https://litellm.vercel.app/docs/providers) | [Models](../models.md) |
|
||||
@@ -125,6 +125,48 @@ praisonai --init "your task description"
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
<Tab title="JavaScript">
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
```bash
|
||||
npm install praisonai
|
||||
```
|
||||
</Step>
|
||||
<Step title="Set API Key">
|
||||
```bash
|
||||
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
</Step>
|
||||
<Step title="Create File">
|
||||
Create `app.js` file
|
||||
|
||||
## Code Example
|
||||
|
||||
<CodeGroup>
|
||||
```javascript Single Agent
|
||||
const { Agent } = require('praisonai');
|
||||
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
|
||||
agent.start('Write a movie script about a robot in Mars');
|
||||
```
|
||||
|
||||
```javascript Multi Agents
|
||||
const { Agent, PraisonAIAgents } = require('praisonai');
|
||||
|
||||
const researchAgent = new Agent({ instructions: 'Research about AI' });
|
||||
const summariseAgent = new Agent({ instructions: 'Summarise research agent\'s findings' });
|
||||
|
||||
const agents = new PraisonAIAgents({ agents: [researchAgent, summariseAgent] });
|
||||
agents.start();
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
<Step title="Run Script">
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
|
||||
@@ -20,6 +20,20 @@ icon: "dumbbell"
|
||||
export HF_TOKEN=xxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
## Initilise praisonai train
|
||||
|
||||
```bash
|
||||
praisonai train init
|
||||
```
|
||||
|
||||
## Required
|
||||
|
||||
1. Huggingface token
|
||||
2. Base model to train on (e.g. unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit)
|
||||
3. Dataset to train on (e.g. yahma/alpaca-cleaned)
|
||||
4. Huggingface model name to upload to (e.g. mervinpraison/llama3.1-instruct) (Optional)
|
||||
5. Ollama model name to upload to (e.g. mervinpraison/llama3.1-instruct) (Optional)
|
||||
|
||||
## To upload to ollama.com (Linux)
|
||||
|
||||
```bash
|
||||
@@ -108,4 +122,21 @@ quantization_method:
|
||||
|
||||
```bash
|
||||
praisonai train
|
||||
```
|
||||
|
||||
## wandb
|
||||
|
||||
```bash
|
||||
wandb login
|
||||
```
|
||||
|
||||
<Note>
|
||||
Get the key from [here](https://wandb.ai/site/login)
|
||||
</Note>
|
||||
|
||||
```bash
|
||||
export PRAISON_WANDB=True
|
||||
export WANDB_LOG_MODEL=checkpoint
|
||||
export WANDB_PROJECT=praisonai-test
|
||||
export PRAISON_WANDB_RUN_NAME=praisonai-train
|
||||
```
|
||||
@@ -0,0 +1,158 @@
|
||||
---
|
||||
title: "Deepseek Streamlit UI"
|
||||
description: "Create interactive chat interfaces with Deepseek models using Streamlit"
|
||||
icon: "window"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> UI[("Streamlit UI")]
|
||||
VDB[(Vector DB)] --> Agent
|
||||
DS[("Deepseek")] --> Agent
|
||||
UI --> Agent[("Knowledge Agent")]
|
||||
Agent --> |Query| VDB
|
||||
Agent --> Out[Output]
|
||||
Out --> UI
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style UI fill:#FF4B4B,color:#fff,shape:circle
|
||||
style DS fill:#4169E1,color:#fff,shape:circle
|
||||
style Agent fill:#2E8B57,color:#fff,shape:circle
|
||||
style VDB fill:#4169E1,color:#fff,shape:cylinder
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install required packages:
|
||||
```bash
|
||||
pip install "praisonaiagents[knowledge]" streamlit ollama
|
||||
```
|
||||
|
||||
<Note>
|
||||
streamlit for UI
|
||||
ollama for Deepseek model hosting
|
||||
praisonaiagents[knowledge] for RAG capabilities
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Setup Model">
|
||||
Pull Deepseek model:
|
||||
```bash
|
||||
# Large Language Model
|
||||
ollama pull deepseek-r1
|
||||
|
||||
# Embedding Model
|
||||
ollama pull nomic-embed-text
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Setup Environment">
|
||||
Configure environment:
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
export OPENAI_API_KEY=fake-key
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create File">
|
||||
Create a new file called `app.py` and add the following code:
|
||||
</Step>
|
||||
|
||||
<Step title="Run Application">
|
||||
Start the Streamlit application:
|
||||
```bash
|
||||
streamlit run app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Code
|
||||
|
||||
```python
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
def init_agent():
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"],
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
st.title("Knowledge Agent Chat")
|
||||
|
||||
if "agent" not in st.session_state:
|
||||
st.session_state.agent = init_agent()
|
||||
st.session_state.messages = []
|
||||
|
||||
if "messages" in st.session_state:
|
||||
for message in st.session_state.messages:
|
||||
with st.chat_message(message["role"]):
|
||||
st.markdown(message["content"])
|
||||
|
||||
prompt = st.chat_input("Ask a question...")
|
||||
|
||||
if prompt:
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
with st.chat_message("user"):
|
||||
st.markdown(prompt)
|
||||
|
||||
with st.chat_message("assistant"):
|
||||
response = st.session_state.agent.start(prompt)
|
||||
st.markdown(response)
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Interactive Chat" icon="comments">
|
||||
Real-time chat interface with message history.
|
||||
</Card>
|
||||
<Card title="Knowledge Base" icon="database">
|
||||
RAG capabilities with ChromaDB integration.
|
||||
</Card>
|
||||
<Card title="Model Integration" icon="server">
|
||||
Uses Deepseek through Ollama.
|
||||
</Card>
|
||||
<Card title="Session Management" icon="clock-rotate-left">
|
||||
Maintains chat history in session state.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Make sure your system meets the requirements for running Deepseek models locally through Ollama.
|
||||
</Note>
|
||||
@@ -0,0 +1,119 @@
|
||||
---
|
||||
title: "Gemini Streamlit UI"
|
||||
description: "Create interactive chat interfaces with Google's Gemini models using Streamlit"
|
||||
icon: "window"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> UI[("Streamlit UI")]
|
||||
VDB[(Vector DB)] --> Agent
|
||||
Gemini[("Gemini")] --> Agent
|
||||
UI --> Agent[("Knowledge Agent")]
|
||||
Agent --> |Query| VDB
|
||||
Agent --> Out[Output]
|
||||
Out --> UI
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style UI fill:#FF4B4B,color:#fff,shape:circle
|
||||
style Gemini fill:#4169E1,color:#fff,shape:circle
|
||||
style Agent fill:#2E8B57,color:#fff,shape:circle
|
||||
style VDB fill:#4169E1,color:#fff,shape:cylinder
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install required packages:
|
||||
```bash
|
||||
pip install "praisonaiagents[llm]" streamlit
|
||||
```
|
||||
|
||||
<Note>
|
||||
streamlit for UI<br />
|
||||
praisonaiagents[llm] for Gemini model access (It uses Litellm)
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Setup Environment">
|
||||
Configure environment:
|
||||
```bash
|
||||
export GOOGLE_API_KEY=your-api-key
|
||||
```
|
||||
|
||||
<Note>
|
||||
Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Create File">
|
||||
Create a new file called `app.py` and add the following code:
|
||||
</Step>
|
||||
|
||||
<Step title="Run Application">
|
||||
Start the Streamlit application:
|
||||
```bash
|
||||
streamlit run app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Code
|
||||
|
||||
```python
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
st.title("Gemini 2.0 Thinking AI Agent")
|
||||
|
||||
# Initialize the agent
|
||||
@st.cache_resource
|
||||
def get_agent():
|
||||
llm_config = {
|
||||
"model": "gemini/gemini-2.0-flash-thinking-exp-01-21",
|
||||
"response_format": {"type": "text"}
|
||||
}
|
||||
|
||||
return Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm=llm_config
|
||||
)
|
||||
|
||||
agent = get_agent()
|
||||
|
||||
# Create text area input field
|
||||
user_question = st.text_area("Ask your question:", height=150)
|
||||
|
||||
# Add ask button
|
||||
if st.button("Ask"):
|
||||
if user_question:
|
||||
with st.spinner('Thinking...'):
|
||||
result = agent.start(user_question)
|
||||
st.write("### Answer")
|
||||
st.write(result)
|
||||
else:
|
||||
st.warning("Please enter a question")
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Interactive Chat" icon="comments">
|
||||
Real-time chat interface with message history.
|
||||
</Card>
|
||||
<Card title="Knowledge Base" icon="database">
|
||||
RAG capabilities with ChromaDB integration.
|
||||
</Card>
|
||||
<Card title="Model Integration" icon="server">
|
||||
Uses Google's Gemini Pro model.
|
||||
</Card>
|
||||
<Card title="Session Management" icon="clock-rotate-left">
|
||||
Maintains chat history in session state.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Make sure you have a valid Google API key and sufficient quota for using Gemini models.
|
||||
</Note>
|
||||
@@ -0,0 +1,158 @@
|
||||
---
|
||||
title: "Ollama Streamlit UI"
|
||||
description: "Create interactive chat interfaces with Ollama models using Streamlit"
|
||||
icon: "window"
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
In[Input] --> UI[("Streamlit UI")]
|
||||
VDB[(Vector DB)] --> Agent
|
||||
Ollama[("Ollama")] --> Agent
|
||||
UI --> Agent[("Knowledge Agent")]
|
||||
Agent --> |Query| VDB
|
||||
Agent --> Out[Output]
|
||||
Out --> UI
|
||||
|
||||
style In fill:#8B0000,color:#fff
|
||||
style UI fill:#FF4B4B,color:#fff,shape:circle
|
||||
style Ollama fill:#4169E1,color:#fff,shape:circle
|
||||
style Agent fill:#2E8B57,color:#fff,shape:circle
|
||||
style VDB fill:#4169E1,color:#fff,shape:cylinder
|
||||
style Out fill:#8B0000,color:#fff
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
Install required packages:
|
||||
```bash
|
||||
pip install "praisonaiagents[knowledge]" streamlit ollama
|
||||
```
|
||||
|
||||
<Note>
|
||||
streamlit for UI
|
||||
ollama for model hosting
|
||||
praisonaiagents[knowledge] for RAG capabilities
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Setup Model">
|
||||
Pull Ollama models:
|
||||
```bash
|
||||
# Large Language Model
|
||||
ollama pull deepseek-r1
|
||||
|
||||
# Embedding Model
|
||||
ollama pull nomic-embed-text
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Setup Environment">
|
||||
Configure environment:
|
||||
```bash
|
||||
export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
export OPENAI_API_KEY=fake-key
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create File">
|
||||
Create a new file called `app.py` and add the following code:
|
||||
</Step>
|
||||
|
||||
<Step title="Run Application">
|
||||
Start the Streamlit application:
|
||||
```bash
|
||||
streamlit run app.py
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Code
|
||||
|
||||
```python
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
def init_agent():
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"],
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
st.title("Knowledge Agent Chat")
|
||||
|
||||
if "agent" not in st.session_state:
|
||||
st.session_state.agent = init_agent()
|
||||
st.session_state.messages = []
|
||||
|
||||
if "messages" in st.session_state:
|
||||
for message in st.session_state.messages:
|
||||
with st.chat_message(message["role"]):
|
||||
st.markdown(message["content"])
|
||||
|
||||
prompt = st.chat_input("Ask a question...")
|
||||
|
||||
if prompt:
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
with st.chat_message("user"):
|
||||
st.markdown(prompt)
|
||||
|
||||
with st.chat_message("assistant"):
|
||||
response = st.session_state.agent.start(prompt)
|
||||
st.markdown(response)
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Interactive Chat" icon="comments">
|
||||
Real-time chat interface with message history.
|
||||
</Card>
|
||||
<Card title="Knowledge Base" icon="database">
|
||||
RAG capabilities with ChromaDB integration.
|
||||
</Card>
|
||||
<Card title="Model Integration" icon="server">
|
||||
Uses Ollama for local model hosting.
|
||||
</Card>
|
||||
<Card title="Session Management" icon="clock-rotate-left">
|
||||
Maintains chat history in session state.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Make sure your system meets the requirements for running models locally through Ollama.
|
||||
</Note>
|
||||
@@ -0,0 +1,142 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import cot_save, cot_upload_to_huggingface
|
||||
from pydantic import BaseModel
|
||||
import os
|
||||
|
||||
# Define Pydantic model for structured output
|
||||
class DecisionModel(BaseModel):
|
||||
response: str
|
||||
decision: str
|
||||
|
||||
def write_csv(file_path, data):
|
||||
"""Write data to CSV file."""
|
||||
if not os.path.exists(file_path):
|
||||
with open(file_path, 'w') as file:
|
||||
file.write(data + '\n')
|
||||
else:
|
||||
with open(file_path, 'a') as file:
|
||||
file.write(data + '\n')
|
||||
return f"Data appended to {file_path}"
|
||||
|
||||
def count_questions(file_path):
|
||||
"""Count lines in file."""
|
||||
with open(file_path, 'r') as file:
|
||||
return sum(1 for _ in file)
|
||||
|
||||
# Keep existing agents with minimal changes
|
||||
qa_generator = Agent(
|
||||
name="Generator",
|
||||
role="Question Creator",
|
||||
goal="Create challenging math and logic questions",
|
||||
backstory="Expert in educational content creation",
|
||||
llm="gpt-4o-mini",
|
||||
tools=[write_csv, count_questions]
|
||||
)
|
||||
|
||||
total_questions_evaluator = Agent(
|
||||
name="TotalQuestionsEvaluator",
|
||||
role="Total Questions Evaluator",
|
||||
goal="Evaluate the total number of questions in qa_pairs.csv file",
|
||||
backstory="Expert in evaluating the total number of questions in a file",
|
||||
llm="gpt-4o-mini",
|
||||
tools=[count_questions],
|
||||
verbose=False
|
||||
)
|
||||
|
||||
cot_generator = Agent(
|
||||
name="COTGenerator",
|
||||
role="Chain of Thought Specialist",
|
||||
goal="Generate and manage chain of thought solutions for Q&A pairs",
|
||||
backstory="Expert in breaking down problems and generating detailed solution steps",
|
||||
tools=[cot_save],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=False
|
||||
)
|
||||
|
||||
upload_to_huggingface = Agent(
|
||||
name="UploadToHuggingface",
|
||||
role="Upload to Huggingface",
|
||||
goal="Upload the generated chain of thought solutions to a Huggingface dataset",
|
||||
backstory="Expert in saving data to Huggingface",
|
||||
tools=[cot_upload_to_huggingface],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=False
|
||||
)
|
||||
|
||||
# Define tasks with workflow improvements
|
||||
generate_task = Task(
|
||||
description="""Generate question and answer in csv format without headers: question, answer and append to qa_pairs.csv file
|
||||
generate 10 unique questions and answers and don't repeat on the same question and answer. Reponse with 'done' when done
|
||||
with append mode as 'a'
|
||||
Example question and answer:
|
||||
question, answer
|
||||
What is the sum of numbers from 1 to 10?, 55
|
||||
Number of r's in the word strawberry, 3
|
||||
""",
|
||||
expected_output="append to qa_pairs.csv file with questions and answers and move to next task",
|
||||
agent=qa_generator,
|
||||
name="generate_task",
|
||||
is_start=True,
|
||||
next_tasks=["evaluate_total_questions"],
|
||||
task_type="decision",
|
||||
condition={
|
||||
"more": "generate_task",
|
||||
"done": "evaluate_total_questions"
|
||||
}
|
||||
)
|
||||
|
||||
evaluate_total_questions_task = Task(
|
||||
description="Evaluate the total number of questions in qa_pairs.csv file is 1",
|
||||
expected_output="Total number of questions in qa_pairs.csv file",
|
||||
agent=total_questions_evaluator,
|
||||
task_type="decision",
|
||||
name="evaluate_total_questions",
|
||||
condition={
|
||||
"more": "generate_task",
|
||||
"done": "generate_cot"
|
||||
}
|
||||
)
|
||||
|
||||
generate_cot_task = Task(
|
||||
name="generate_cot",
|
||||
description="""Generate chain of thought solutions for each question in the input file.
|
||||
Save to cot_solutions.csv file
|
||||
Don't generate chain of thought solutions again after receiving the response from Tool Call
|
||||
After calling the tool, respond with a JSON object:
|
||||
{
|
||||
"response": "done",
|
||||
"decision": "done"
|
||||
}
|
||||
""",
|
||||
expected_output="done",
|
||||
agent=cot_generator,
|
||||
input_file="qa_pairs.csv",
|
||||
task_type="loop",
|
||||
next_tasks=["upload_to_huggingface"],
|
||||
condition={
|
||||
"done": ["upload_to_huggingface"],
|
||||
"exit": [],
|
||||
},
|
||||
output_pydantic=DecisionModel # Use Pydantic model for output validation
|
||||
)
|
||||
|
||||
upload_to_huggingface_task = Task(
|
||||
name="upload_to_huggingface",
|
||||
description="""Upload to Huggingface:
|
||||
1. Save to cot_solutions.csv
|
||||
2. Upload to mervinpraison/cot-dataset""",
|
||||
expected_output="Dataset published successfully",
|
||||
agent=upload_to_huggingface,
|
||||
tools=[cot_upload_to_huggingface]
|
||||
)
|
||||
|
||||
# Initialize workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[qa_generator, total_questions_evaluator, cot_generator, upload_to_huggingface],
|
||||
tasks=[generate_task, evaluate_total_questions_task, generate_cot_task, upload_to_huggingface_task],
|
||||
process="workflow",
|
||||
max_iter=30,
|
||||
verbose=False
|
||||
)
|
||||
|
||||
agents.start()
|
||||
@@ -0,0 +1,15 @@
|
||||
import asyncio
|
||||
from praisonaiagents import ImageAgent
|
||||
|
||||
async def main():
|
||||
agent = ImageAgent(
|
||||
name="ImageCreator",
|
||||
llm="dall-e-3",
|
||||
style="natural"
|
||||
)
|
||||
|
||||
result = await agent.achat("A cute baby sea otter playing with a laptop")
|
||||
print(f"Image generation result: {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,8 @@
|
||||
from praisonaiagents.agent.image_agent import ImageAgent
|
||||
|
||||
# Create an image agent with normal mode
|
||||
agent = ImageAgent(llm="dall-e-3")
|
||||
|
||||
# Generate an image
|
||||
result = agent.chat("A cute baby sea otter playing with a laptop")
|
||||
print("Image generation result:", result)
|
||||
@@ -0,0 +1,9 @@
|
||||
# pip install praisonaiagents
|
||||
# export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
# ollama pull deepseek-r1
|
||||
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(instructions="You are helpful Assisant", llm="deepseek-r1")
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
@@ -0,0 +1,62 @@
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
def init_agent():
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"],
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
st.title("Knowledge Agent Chat")
|
||||
|
||||
if "agent" not in st.session_state:
|
||||
st.session_state.agent = init_agent()
|
||||
st.session_state.messages = []
|
||||
|
||||
if "messages" in st.session_state:
|
||||
for message in st.session_state.messages:
|
||||
with st.chat_message(message["role"]):
|
||||
st.markdown(message["content"])
|
||||
|
||||
prompt = st.chat_input("Ask a question...")
|
||||
|
||||
if prompt:
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
with st.chat_message("user"):
|
||||
st.markdown(prompt)
|
||||
|
||||
with st.chat_message("assistant"):
|
||||
response = st.session_state.agent.start(prompt)
|
||||
st.markdown(response)
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
@@ -0,0 +1,39 @@
|
||||
from praisonaiagents import Agent
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
agent = Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"], # Indexing
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
agent.start("What is KAG in one line?") # Retrieval
|
||||
@@ -0,0 +1,45 @@
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Detailed LLM configuration
|
||||
llm_config = {
|
||||
"model": "gemini/gemini-1.5-flash-latest", # Model name without provider prefix
|
||||
|
||||
# Core settings
|
||||
"temperature": 0.7, # Controls randomness (like temperature)
|
||||
"timeout": 30, # Timeout in seconds
|
||||
"top_p": 0.9, # Nucleus sampling parameter
|
||||
"max_tokens": 1000, # Max tokens in response
|
||||
|
||||
# Advanced parameters
|
||||
"presence_penalty": 0.1, # Penalize repetition of topics (-2.0 to 2.0)
|
||||
"frequency_penalty": 0.1, # Penalize token repetition (-2.0 to 2.0)
|
||||
|
||||
# API settings (optional)
|
||||
"api_key": None, # Your API key (or use environment variable)
|
||||
"base_url": None, # Custom API endpoint if needed
|
||||
|
||||
# Response formatting
|
||||
"response_format": { # Force specific response format
|
||||
"type": "text" # Options: "text", "json_object"
|
||||
},
|
||||
|
||||
# Additional controls
|
||||
"seed": 42, # For reproducible responses
|
||||
"stop_phrases": ["##", "END"], # Custom stop sequences
|
||||
}
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful Assistant specialized in scientific explanations. "
|
||||
"Provide clear, accurate, and engaging responses.",
|
||||
llm=llm_config, # Pass the detailed configuration
|
||||
verbose=True, # Enable detailed output
|
||||
markdown=True, # Format responses in markdown
|
||||
self_reflect=True, # Enable self-reflection
|
||||
max_reflect=3, # Maximum reflection iterations
|
||||
min_reflect=1 # Minimum reflection iterations
|
||||
)
|
||||
|
||||
# Test the agent
|
||||
response = agent.start("Why is the sky blue? Please explain in simple terms.")
|
||||
|
||||
print(response)
|
||||
@@ -0,0 +1,18 @@
|
||||
import asyncio
|
||||
from praisonaiagents import Agent
|
||||
|
||||
async def main():
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Use achat instead of start/chat for async operation
|
||||
response = await agent.achat("Why sky is Blue in 1000 words?")
|
||||
print(response)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the async main function
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,10 @@
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="gemini/gemini-1.5-flash-8b",
|
||||
self_reflect=True,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
@@ -0,0 +1,9 @@
|
||||
# pip install praisonaiagents
|
||||
# export OPENAI_BASE_URL=http://localhost:11434/v1
|
||||
# ollama pull deepseek-r1
|
||||
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(instructions="You are helpful Assisant", llm="deepseek-r1")
|
||||
|
||||
agent.start("Why sky is Blue?")
|
||||
@@ -0,0 +1,32 @@
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
st.title("Gemini 2.0 Thinking AI Agent")
|
||||
|
||||
# Initialize the agent
|
||||
@st.cache_resource
|
||||
def get_agent():
|
||||
llm_config = {
|
||||
"model": "gemini/gemini-2.0-flash-thinking-exp-01-21",
|
||||
"response_format": {"type": "text"}
|
||||
}
|
||||
|
||||
return Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm=llm_config
|
||||
)
|
||||
|
||||
agent = get_agent()
|
||||
|
||||
# Create text area input field
|
||||
user_question = st.text_area("Ask your question:", height=150)
|
||||
|
||||
# Add ask button
|
||||
if st.button("Ask"):
|
||||
if user_question:
|
||||
with st.spinner('Thinking...'):
|
||||
result = agent.start(user_question)
|
||||
st.write("### Answer")
|
||||
st.write(result)
|
||||
else:
|
||||
st.warning("Please enter a question")
|
||||
@@ -0,0 +1,62 @@
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent
|
||||
|
||||
def init_agent():
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "praison",
|
||||
"path": ".praison"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "deepseek-r1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
"embedding_dims": 1536
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return Agent(
|
||||
name="Knowledge Agent",
|
||||
instructions="You answer questions based on the provided knowledge.",
|
||||
knowledge=["kag-research-paper.pdf"],
|
||||
knowledge_config=config,
|
||||
user_id="user1",
|
||||
llm="deepseek-r1"
|
||||
)
|
||||
|
||||
st.title("Knowledge Agent Chat")
|
||||
|
||||
if "agent" not in st.session_state:
|
||||
st.session_state.agent = init_agent()
|
||||
st.session_state.messages = []
|
||||
|
||||
if "messages" in st.session_state:
|
||||
for message in st.session_state.messages:
|
||||
with st.chat_message(message["role"]):
|
||||
st.markdown(message["content"])
|
||||
|
||||
prompt = st.chat_input("Ask a question...")
|
||||
|
||||
if prompt:
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
with st.chat_message("user"):
|
||||
st.markdown(prompt)
|
||||
|
||||
with st.chat_message("assistant"):
|
||||
response = st.session_state.agent.start(prompt)
|
||||
st.markdown(response)
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
+1
-1
@@ -3,7 +3,7 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.54.tar.gz"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.71.tar.gz"
|
||||
sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum
|
||||
license "MIT"
|
||||
|
||||
|
||||
+93
-8
@@ -25,7 +25,6 @@ CALL_MODULE_AVAILABLE = False
|
||||
CREWAI_AVAILABLE = False
|
||||
AUTOGEN_AVAILABLE = False
|
||||
PRAISONAI_AVAILABLE = False
|
||||
|
||||
try:
|
||||
# Create necessary directories and set CHAINLIT_APP_ROOT
|
||||
if "CHAINLIT_APP_ROOT" not in os.environ:
|
||||
@@ -140,6 +139,8 @@ class PraisonAI:
|
||||
provided arguments.
|
||||
"""
|
||||
args = self.parse_args()
|
||||
# Store args for use in handle_direct_prompt
|
||||
self.args = args
|
||||
invocation_cmd = "praisonai"
|
||||
version_string = f"PraisonAI version {__version__}"
|
||||
|
||||
@@ -148,8 +149,16 @@ class PraisonAI:
|
||||
if args.command:
|
||||
if args.command.startswith("tests.test"): # Argument used for testing purposes
|
||||
print("test")
|
||||
return "test"
|
||||
else:
|
||||
self.agent_file = args.command
|
||||
elif hasattr(args, 'direct_prompt') and args.direct_prompt:
|
||||
result = self.handle_direct_prompt(args.direct_prompt)
|
||||
print(result)
|
||||
return result
|
||||
else:
|
||||
# Default to agents.yaml if no command provided
|
||||
self.agent_file = "agents.yaml"
|
||||
|
||||
if args.deploy:
|
||||
from .deploy import CloudDeployer
|
||||
@@ -192,6 +201,10 @@ class PraisonAI:
|
||||
)
|
||||
with open('config.yaml', 'w') as f:
|
||||
yaml.dump(config, f, default_flow_style=False, indent=2)
|
||||
else:
|
||||
# Load existing config
|
||||
with open(config_yaml_destination, 'r') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# Overwrite huggingface_save and ollama_save if --hf or --ollama are provided
|
||||
if args.hf:
|
||||
@@ -285,14 +298,18 @@ class PraisonAI:
|
||||
"""
|
||||
Parse the command-line arguments for the PraisonAI CLI.
|
||||
"""
|
||||
# Define special commands
|
||||
special_commands = ['chat', 'code', 'call', 'realtime', 'train', 'ui']
|
||||
|
||||
parser = argparse.ArgumentParser(prog="praisonai", description="praisonAI command-line interface")
|
||||
parser.add_argument("--framework", choices=["crewai", "autogen", "praisonai"], help="Specify the framework")
|
||||
parser.add_argument("--ui", choices=["chainlit", "gradio"], help="Specify the UI framework (gradio or chainlit).")
|
||||
parser.add_argument("--auto", nargs=argparse.REMAINDER, help="Enable auto mode and pass arguments for it")
|
||||
parser.add_argument("--init", nargs=argparse.REMAINDER, help="Initialize agents with optional topic")
|
||||
parser.add_argument("command", nargs="?", help="Command to run")
|
||||
parser.add_argument("command", nargs="?", help="Command to run or direct prompt")
|
||||
parser.add_argument("--deploy", action="store_true", help="Deploy the application")
|
||||
parser.add_argument("--model", type=str, help="Model name")
|
||||
parser.add_argument("--llm", type=str, help="LLM model to use for direct prompts")
|
||||
parser.add_argument("--hf", type=str, help="Hugging Face model name")
|
||||
parser.add_argument("--ollama", type=str, help="Ollama model name")
|
||||
parser.add_argument("--dataset", type=str, help="Dataset name for training", default="yahma/alpaca-cleaned")
|
||||
@@ -301,6 +318,7 @@ class PraisonAI:
|
||||
parser.add_argument("--public", action="store_true", help="Use ngrok to expose the server publicly (only with --call)")
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
|
||||
# Handle special cases first
|
||||
if unknown_args and unknown_args[0] == '-b' and unknown_args[1] == 'api:app':
|
||||
args.command = 'agents.yaml'
|
||||
if args.command == 'api:app' or args.command == '/app/api:app':
|
||||
@@ -331,9 +349,7 @@ class PraisonAI:
|
||||
call_module.main(call_args)
|
||||
sys.exit(0)
|
||||
|
||||
# Handle special commands first
|
||||
special_commands = ['chat', 'code', 'call', 'realtime', 'train', 'ui']
|
||||
|
||||
# Handle special commands
|
||||
if args.command in special_commands:
|
||||
if args.command == 'chat':
|
||||
if not CHAINLIT_AVAILABLE:
|
||||
@@ -380,9 +396,8 @@ class PraisonAI:
|
||||
sys.exit(0)
|
||||
|
||||
elif args.command == 'train':
|
||||
print("[red]ERROR: Train feature is not installed. Install with:[/red]")
|
||||
print("\npip install \"praisonai[train]\"\n")
|
||||
sys.exit(1)
|
||||
package_root = os.path.dirname(os.path.abspath(__file__))
|
||||
config_yaml_destination = os.path.join(os.getcwd(), 'config.yaml')
|
||||
|
||||
elif args.command == 'ui':
|
||||
if not CHAINLIT_AVAILABLE:
|
||||
@@ -402,8 +417,78 @@ class PraisonAI:
|
||||
print("pip install praisonaiagents # For PraisonAIAgents\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Handle direct prompt if command is not a special command or file
|
||||
if args.command and not args.command.endswith('.yaml') and args.command not in special_commands:
|
||||
args.direct_prompt = args.command
|
||||
args.command = None
|
||||
|
||||
return args
|
||||
|
||||
def handle_direct_prompt(self, prompt):
|
||||
"""
|
||||
Handle direct prompt by creating a single agent and running it.
|
||||
"""
|
||||
if PRAISONAI_AVAILABLE:
|
||||
agent_config = {
|
||||
"name": "DirectAgent",
|
||||
"role": "Assistant",
|
||||
"goal": "Complete the given task",
|
||||
"backstory": "You are a helpful AI assistant"
|
||||
}
|
||||
|
||||
# Add llm if specified
|
||||
if hasattr(self, 'args') and self.args.llm:
|
||||
agent_config["llm"] = self.args.llm
|
||||
|
||||
agent = PraisonAgent(**agent_config)
|
||||
result = agent.start(prompt)
|
||||
return ""
|
||||
elif CREWAI_AVAILABLE:
|
||||
agent_config = {
|
||||
"name": "DirectAgent",
|
||||
"role": "Assistant",
|
||||
"goal": "Complete the given task",
|
||||
"backstory": "You are a helpful AI assistant"
|
||||
}
|
||||
|
||||
# Add llm if specified
|
||||
if hasattr(self, 'args') and self.args.llm:
|
||||
agent_config["llm"] = self.args.llm
|
||||
|
||||
agent = Agent(**agent_config)
|
||||
task = Task(
|
||||
description=prompt,
|
||||
agent=agent
|
||||
)
|
||||
crew = Crew(
|
||||
agents=[agent],
|
||||
tasks=[task]
|
||||
)
|
||||
return crew.kickoff()
|
||||
elif AUTOGEN_AVAILABLE:
|
||||
config_list = self.config_list
|
||||
# Add llm if specified
|
||||
if hasattr(self, 'args') and self.args.llm:
|
||||
config_list[0]['model'] = self.args.llm
|
||||
|
||||
assistant = autogen.AssistantAgent(
|
||||
name="DirectAgent",
|
||||
llm_config={"config_list": config_list}
|
||||
)
|
||||
user_proxy = autogen.UserProxyAgent(
|
||||
name="UserProxy",
|
||||
code_execution_config={"work_dir": "coding"}
|
||||
)
|
||||
user_proxy.initiate_chat(assistant, message=prompt)
|
||||
return "Task completed"
|
||||
else:
|
||||
print("[red]ERROR: No framework is installed. Please install at least one framework:[/red]")
|
||||
print("\npip install \"praisonai\\[crewai]\" # For CrewAI")
|
||||
print("pip install \"praisonai\\[autogen]\" # For AutoGen")
|
||||
print("pip install \"praisonai\\[crewai,autogen]\" # For both frameworks\n")
|
||||
print("pip install praisonaiagents # For PraisonAIAgents\n")
|
||||
sys.exit(1)
|
||||
|
||||
def create_chainlit_chat_interface(self):
|
||||
"""
|
||||
Create a Chainlit interface for the chat application.
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.54 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.71 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -11,6 +11,38 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
# Linux
|
||||
MINICONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh"
|
||||
|
||||
# Install libcurl development package if not present (Debian based)
|
||||
if command -v dpkg &> /dev/null; then
|
||||
if ! dpkg -s libcurl4-openssl-dev &> /dev/null; then
|
||||
echo "libcurl4-openssl-dev is not installed. Installing..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libcurl4-openssl-dev
|
||||
else
|
||||
echo "libcurl4-openssl-dev is already installed."
|
||||
fi
|
||||
else
|
||||
echo "Non-Debian based Linux detected. Please ensure libcurl development libraries are installed."
|
||||
fi
|
||||
|
||||
# Check if ollama is installed and executable; if not, install it
|
||||
if ! command -v ollama &> /dev/null; then
|
||||
echo "Ollama is not installed. Installing Ollama..."
|
||||
curl -fsSL https://ollama.com/install.sh | sh
|
||||
|
||||
# Generate SSH key non-interactively only if it doesn't already exist
|
||||
if [ ! -f ~/.ssh/id_ed25519 ]; then
|
||||
echo "Generating SSH key for Ollama..."
|
||||
ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519 -q
|
||||
else
|
||||
echo "SSH key ~/.ssh/id_ed25519 already exists. Skipping generation."
|
||||
fi
|
||||
echo "Copying SSH key to /usr/share/ollama/.ollama..."
|
||||
sudo cp ~/.ssh/id_ed25519 /usr/share/ollama/.ollama
|
||||
else
|
||||
echo "Ollama is already installed."
|
||||
fi
|
||||
|
||||
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
||||
# Windows
|
||||
MINICONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe"
|
||||
@@ -21,12 +53,12 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if conda is already installed
|
||||
# Check if conda is installed
|
||||
if ! command -v conda &> /dev/null; then
|
||||
echo "Conda is not installed. Installing Miniconda..."
|
||||
wget $MINICONDA_URL -O ~/miniconda.sh
|
||||
bash ~/miniconda.sh -b -p $HOME/miniconda
|
||||
source $HOME/miniconda/bin/activate
|
||||
wget "$MINICONDA_URL" -O ~/miniconda.sh
|
||||
bash ~/miniconda.sh -b -p "$HOME/miniconda"
|
||||
source "$HOME/miniconda/bin/activate"
|
||||
conda init
|
||||
else
|
||||
echo "Conda is already installed."
|
||||
@@ -34,39 +66,40 @@ fi
|
||||
|
||||
# Create and activate the Conda environment
|
||||
ENV_NAME="praison_env"
|
||||
if conda info --envs | grep -q $ENV_NAME; then
|
||||
if conda info --envs | grep -q "$ENV_NAME"; then
|
||||
echo "Environment $ENV_NAME already exists. Recreating..."
|
||||
conda env remove -y -n $ENV_NAME # Remove existing environment
|
||||
conda env remove -y -n "$ENV_NAME"
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS (both Intel and M1/M2)
|
||||
conda create --name $ENV_NAME python=3.10 pytorch=2.3.0 -c pytorch -y
|
||||
conda create --name "$ENV_NAME" python=3.10 pytorch=2.3.0 -c pytorch -y
|
||||
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
# Linux
|
||||
conda create --name $ENV_NAME python=3.10 pytorch=2.3.0 cudatoolkit=11.8 -c pytorch -c nvidia -y
|
||||
conda create --name "$ENV_NAME" python=3.10 pytorch=2.3.0 cudatoolkit=11.8 -c pytorch -c nvidia -y
|
||||
fi
|
||||
# conda activate $ENV_NAME
|
||||
else
|
||||
echo "Creating new environment $ENV_NAME..."
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS (both Intel and M1/M2)
|
||||
conda create --name $ENV_NAME python=3.10 pytorch=2.3.0 -c pytorch -y
|
||||
conda create --name "$ENV_NAME" python=3.10 pytorch=2.3.0 -c pytorch -y
|
||||
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
# Linux
|
||||
conda create --name $ENV_NAME python=3.10 pytorch=2.3.0 cudatoolkit=11.8 -c pytorch -c nvidia -y
|
||||
conda create --name "$ENV_NAME" python=3.10 pytorch=2.3.0 cudatoolkit=11.8 -c pytorch -c nvidia -y
|
||||
fi
|
||||
# conda activate $ENV_NAME
|
||||
fi
|
||||
|
||||
# source $HOME/miniconda/bin/activate $ENV_NAME
|
||||
# Activate the environment
|
||||
source "$HOME/miniconda/bin/activate" "$ENV_NAME"
|
||||
|
||||
# Get full path of pip
|
||||
PIP_FULL_PATH=$(conda run -n $ENV_NAME which pip)
|
||||
# Install cmake via conda
|
||||
echo "Installing cmake..."
|
||||
conda install -y cmake
|
||||
|
||||
# Install other packages within the activated environment
|
||||
# Use PIP_FULL_PATH to run pip commands
|
||||
# Get full path of pip within the activated environment
|
||||
PIP_FULL_PATH=$(conda run -n "$ENV_NAME" which pip)
|
||||
|
||||
# Install other packages using pip
|
||||
$PIP_FULL_PATH install --upgrade pip
|
||||
$PIP_FULL_PATH install "xformers==0.0.26.post1"
|
||||
$PIP_FULL_PATH install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git@4e570be9ae4ced8cdc64e498125708e34942befc"
|
||||
$PIP_FULL_PATH install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git@038e6d4c8d40207a87297ab3aaf787c19b1006d1"
|
||||
$PIP_FULL_PATH install --no-deps "trl<0.9.0" peft accelerate bitsandbytes
|
||||
$PIP_FULL_PATH install unsloth_zoo
|
||||
$PIP_FULL_PATH install cut_cross_entropy
|
||||
$PIP_FULL_PATH install sentencepiece protobuf datasets huggingface_hub hf_transfer wandb
|
||||
|
||||
echo "Setup completed successfully!"
|
||||
+439
-153
@@ -1,168 +1,283 @@
|
||||
import subprocess
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This script finetunes a model using Unsloth’s fast training framework.
|
||||
It supports both ShareGPT and Alpaca‑style datasets by converting raw conversation
|
||||
data into plain-text prompts using a chat template, then pre‑tokenizing the prompts.
|
||||
Extra debug logging is added to help trace the root cause of errors.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
import torch
|
||||
import shutil
|
||||
import subprocess
|
||||
from transformers import TextStreamer
|
||||
from unsloth import FastLanguageModel, is_bfloat16_supported
|
||||
from trl import SFTTrainer
|
||||
from transformers import TrainingArguments
|
||||
from datasets import load_dataset, concatenate_datasets, Dataset
|
||||
from datasets import load_dataset, concatenate_datasets
|
||||
from psutil import virtual_memory
|
||||
from unsloth.chat_templates import standardize_sharegpt, get_chat_template
|
||||
from functools import partial
|
||||
|
||||
class train:
|
||||
#####################################
|
||||
# Step 1: Formatting Raw Conversations
|
||||
#####################################
|
||||
def formatting_prompts_func(examples, tokenizer):
|
||||
"""
|
||||
Converts each example’s conversation into a single plain-text prompt.
|
||||
If the example has a "conversations" field, process it as ShareGPT-style.
|
||||
Otherwise, assume Alpaca-style data with "instruction", "input", and "output" fields.
|
||||
"""
|
||||
print("DEBUG: formatting_prompts_func() received batch with keys:", list(examples.keys()))
|
||||
texts = []
|
||||
# Check if the example has a "conversations" field.
|
||||
if "conversations" in examples:
|
||||
for convo in examples["conversations"]:
|
||||
try:
|
||||
formatted = tokenizer.apply_chat_template(
|
||||
convo,
|
||||
tokenize=False, # Return a plain string
|
||||
add_generation_prompt=False
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"ERROR in apply_chat_template (conversations): {e}")
|
||||
formatted = ""
|
||||
# Flatten list if necessary
|
||||
if isinstance(formatted, list):
|
||||
formatted = formatted[0] if len(formatted) == 1 else "\n".join(formatted)
|
||||
texts.append(formatted)
|
||||
else:
|
||||
# Assume Alpaca format: use "instruction", "input", and "output" keys.
|
||||
instructions = examples.get("instruction", [])
|
||||
inputs_list = examples.get("input", [])
|
||||
outputs_list = examples.get("output", [])
|
||||
# If any field is missing, replace with empty string.
|
||||
for ins, inp, out in zip(instructions, inputs_list, outputs_list):
|
||||
# Create a conversation-like structure.
|
||||
convo = [
|
||||
{"role": "user", "content": ins + (f"\nInput: {inp}" if inp.strip() != "" else "")},
|
||||
{"role": "assistant", "content": out}
|
||||
]
|
||||
try:
|
||||
formatted = tokenizer.apply_chat_template(
|
||||
convo,
|
||||
tokenize=False,
|
||||
add_generation_prompt=False
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"ERROR in apply_chat_template (alpaca): {e}")
|
||||
formatted = ""
|
||||
if isinstance(formatted, list):
|
||||
formatted = formatted[0] if len(formatted) == 1 else "\n".join(formatted)
|
||||
texts.append(formatted)
|
||||
if texts:
|
||||
print("DEBUG: Raw texts sample (first 200 chars):", texts[0][:200])
|
||||
return {"text": texts}
|
||||
|
||||
#####################################
|
||||
# Step 2: Tokenizing the Prompts
|
||||
#####################################
|
||||
def tokenize_function(examples, hf_tokenizer, max_length):
|
||||
"""
|
||||
Tokenizes a batch of text prompts with padding and truncation enabled.
|
||||
"""
|
||||
flat_texts = []
|
||||
for t in examples["text"]:
|
||||
if isinstance(t, list):
|
||||
t = t[0] if len(t) == 1 else " ".join(t)
|
||||
flat_texts.append(t)
|
||||
print("DEBUG: Tokenizing a batch of size:", len(flat_texts))
|
||||
tokenized = hf_tokenizer(
|
||||
flat_texts,
|
||||
padding="max_length",
|
||||
truncation=True,
|
||||
max_length=max_length,
|
||||
return_tensors="pt",
|
||||
)
|
||||
tokenized = {key: value.tolist() for key, value in tokenized.items()}
|
||||
sample_key = list(tokenized.keys())[0]
|
||||
print("DEBUG: Tokenized sample (first 10 tokens of", sample_key, "):", tokenized[sample_key][0][:10])
|
||||
return tokenized
|
||||
|
||||
#####################################
|
||||
# Main Training Class
|
||||
#####################################
|
||||
class TrainModel:
|
||||
def __init__(self, config_path="config.yaml"):
|
||||
self.load_config(config_path)
|
||||
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
self.model, self.tokenizer = None, None
|
||||
self.model = None
|
||||
self.hf_tokenizer = None # The underlying HF tokenizer
|
||||
self.chat_tokenizer = None # Chat wrapper for formatting
|
||||
|
||||
def load_config(self, path):
|
||||
with open(path, "r") as file:
|
||||
self.config = yaml.safe_load(file)
|
||||
print("DEBUG: Loaded config:", self.config)
|
||||
|
||||
def print_system_info(self):
|
||||
print(f"PyTorch version: {torch.__version__}")
|
||||
print(f"CUDA version: {torch.version.cuda}")
|
||||
print("DEBUG: PyTorch version:", torch.__version__)
|
||||
print("DEBUG: CUDA version:", torch.version.cuda)
|
||||
if torch.cuda.is_available():
|
||||
device_capability = torch.cuda.get_device_capability()
|
||||
print(f"CUDA Device Capability: {device_capability}")
|
||||
print("DEBUG: CUDA Device Capability:", torch.cuda.get_device_capability())
|
||||
else:
|
||||
print("CUDA is not available")
|
||||
|
||||
python_version = sys.version
|
||||
pip_version = subprocess.check_output(['pip', '--version']).decode().strip()
|
||||
python_path = sys.executable
|
||||
pip_path = subprocess.check_output(['which', 'pip']).decode().strip()
|
||||
print(f"Python Version: {python_version}")
|
||||
print(f"Pip Version: {pip_version}")
|
||||
print(f"Python Path: {python_path}")
|
||||
print(f"Pip Path: {pip_path}")
|
||||
print("DEBUG: CUDA is not available")
|
||||
print("DEBUG: Python Version:", sys.version)
|
||||
print("DEBUG: Python Path:", sys.executable)
|
||||
|
||||
def check_gpu(self):
|
||||
gpu_stats = torch.cuda.get_device_properties(0)
|
||||
print(f"GPU = {gpu_stats.name}. Max memory = {round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)} GB.")
|
||||
print(f"DEBUG: GPU = {gpu_stats.name}. Max memory = {round(gpu_stats.total_memory/(1024**3),3)} GB.")
|
||||
|
||||
def check_ram(self):
|
||||
ram_gb = virtual_memory().total / 1e9
|
||||
print('Your runtime has {:.1f} gigabytes of available RAM\n'.format(ram_gb))
|
||||
print(f"DEBUG: Your runtime has {ram_gb:.1f} gigabytes of available RAM")
|
||||
if ram_gb < 20:
|
||||
print('Not using a high-RAM runtime')
|
||||
print("DEBUG: Not using a high-RAM runtime")
|
||||
else:
|
||||
print('You are using a high-RAM runtime!')
|
||||
|
||||
# def install_packages(self):
|
||||
# subprocess.run(["pip", "install", "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git@4e570be9ae4ced8cdc64e498125708e34942befc"])
|
||||
# subprocess.run(["pip", "install", "--no-deps", "trl<0.9.0", "peft==0.12.0", "accelerate==0.33.0", "bitsandbytes==0.43.3"])
|
||||
print("DEBUG: You are using a high-RAM runtime!")
|
||||
|
||||
def prepare_model(self):
|
||||
self.model, self.tokenizer = FastLanguageModel.from_pretrained(
|
||||
print("DEBUG: Preparing model and tokenizer...")
|
||||
self.model, original_tokenizer = FastLanguageModel.from_pretrained(
|
||||
model_name=self.config["model_name"],
|
||||
max_seq_length=self.config["max_seq_length"],
|
||||
dtype=None,
|
||||
load_in_4bit=self.config["load_in_4bit"]
|
||||
load_in_4bit=self.config["load_in_4bit"],
|
||||
)
|
||||
print("DEBUG: Model and original tokenizer loaded.")
|
||||
if original_tokenizer.pad_token is None:
|
||||
original_tokenizer.pad_token = original_tokenizer.eos_token
|
||||
original_tokenizer.model_max_length = self.config["max_seq_length"]
|
||||
self.chat_tokenizer = get_chat_template(original_tokenizer, chat_template="llama-3.1")
|
||||
self.hf_tokenizer = original_tokenizer
|
||||
print("DEBUG: Chat tokenizer created; HF tokenizer saved.")
|
||||
self.model = FastLanguageModel.get_peft_model(
|
||||
self.model,
|
||||
r=self.config["lora_r"],
|
||||
target_modules=self.config["lora_target_modules"],
|
||||
lora_alpha=self.config["lora_alpha"],
|
||||
lora_dropout=self.config["lora_dropout"],
|
||||
bias=self.config["lora_bias"],
|
||||
use_gradient_checkpointing=self.config["use_gradient_checkpointing"],
|
||||
random_state=self.config["random_state"],
|
||||
use_rslora=self.config["use_rslora"],
|
||||
loftq_config=self.config["loftq_config"],
|
||||
r=16,
|
||||
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
|
||||
lora_alpha=16,
|
||||
lora_dropout=0,
|
||||
bias="none",
|
||||
use_gradient_checkpointing="unsloth",
|
||||
random_state=3407,
|
||||
use_rslora=False,
|
||||
loftq_config=None,
|
||||
)
|
||||
print("DEBUG: LoRA adapters added.")
|
||||
|
||||
def process_dataset(self, dataset_info):
|
||||
dataset_name = dataset_info["name"]
|
||||
split_type = dataset_info.get("split_type", "train")
|
||||
processing_func = getattr(self, dataset_info.get("processing_func", "format_prompts"))
|
||||
rename = dataset_info.get("rename", {})
|
||||
filter_data = dataset_info.get("filter_data", False)
|
||||
filter_column_value = dataset_info.get("filter_column_value", "id")
|
||||
filter_value = dataset_info.get("filter_value", "alpaca")
|
||||
num_samples = dataset_info.get("num_samples", 20000)
|
||||
|
||||
print(f"DEBUG: Loading dataset '{dataset_name}' split '{split_type}'...")
|
||||
dataset = load_dataset(dataset_name, split=split_type)
|
||||
|
||||
if rename:
|
||||
dataset = dataset.rename_columns(rename)
|
||||
if filter_data:
|
||||
dataset = dataset.filter(lambda example: filter_value in example[filter_column_value]).shuffle(seed=42).select(range(num_samples))
|
||||
dataset = dataset.map(processing_func, batched=True)
|
||||
print("DEBUG: Dataset columns:", dataset.column_names)
|
||||
if "conversations" in dataset.column_names:
|
||||
print("DEBUG: Standardizing dataset (ShareGPT style)...")
|
||||
dataset = standardize_sharegpt(dataset)
|
||||
else:
|
||||
print("DEBUG: Dataset does not have 'conversations'; assuming Alpaca format.")
|
||||
print("DEBUG: Applying formatting function to dataset...")
|
||||
format_func = partial(formatting_prompts_func, tokenizer=self.chat_tokenizer)
|
||||
dataset = dataset.map(format_func, batched=True, remove_columns=dataset.column_names)
|
||||
sample = dataset[0]
|
||||
print("DEBUG: Sample processed example keys:", list(sample.keys()))
|
||||
if "text" in sample:
|
||||
print("DEBUG: Sample processed 'text' type:", type(sample["text"]))
|
||||
print("DEBUG: Sample processed 'text' content (first 200 chars):", sample["text"][:200])
|
||||
else:
|
||||
print("DEBUG: Processed sample does not contain 'text'.")
|
||||
return dataset
|
||||
|
||||
def format_prompts(self, examples):
|
||||
alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
|
||||
|
||||
### Instruction:
|
||||
{}
|
||||
|
||||
### Input:
|
||||
{}
|
||||
|
||||
### Response:
|
||||
{}"""
|
||||
texts = [alpaca_prompt.format(ins, inp, out) + self.tokenizer.eos_token for ins, inp, out in zip(examples["instruction"], examples["input"], examples["output"])]
|
||||
return {"text": texts}
|
||||
def tokenize_dataset(self, dataset):
|
||||
print("DEBUG: Tokenizing the entire dataset...")
|
||||
tokenized_dataset = dataset.map(
|
||||
lambda examples: tokenize_function(examples, self.hf_tokenizer, self.config["max_seq_length"]),
|
||||
batched=True
|
||||
)
|
||||
tokenized_dataset = tokenized_dataset.remove_columns(["text"])
|
||||
print("DEBUG: Tokenized dataset sample keys:", tokenized_dataset[0].keys())
|
||||
return tokenized_dataset
|
||||
|
||||
def load_datasets(self):
|
||||
datasets = []
|
||||
for dataset_info in self.config["dataset"]:
|
||||
print("DEBUG: Processing dataset info:", dataset_info)
|
||||
datasets.append(self.process_dataset(dataset_info))
|
||||
return concatenate_datasets(datasets)
|
||||
combined = concatenate_datasets(datasets)
|
||||
print("DEBUG: Combined dataset has", len(combined), "examples.")
|
||||
return combined
|
||||
|
||||
def train_model(self):
|
||||
dataset = self.load_datasets()
|
||||
print("DEBUG: Starting training...")
|
||||
raw_dataset = self.load_datasets()
|
||||
tokenized_dataset = self.tokenize_dataset(raw_dataset)
|
||||
print("DEBUG: Dataset tokenization complete.")
|
||||
training_args = TrainingArguments(
|
||||
per_device_train_batch_size=2,
|
||||
gradient_accumulation_steps=4,
|
||||
warmup_steps=5,
|
||||
max_steps=60,
|
||||
learning_rate=2e-4,
|
||||
fp16=not is_bfloat16_supported(),
|
||||
bf16=is_bfloat16_supported(),
|
||||
logging_steps=1,
|
||||
optim="adamw_8bit",
|
||||
weight_decay=0.01,
|
||||
lr_scheduler_type="linear",
|
||||
seed=3407,
|
||||
output_dir="outputs",
|
||||
report_to="none" if not os.getenv("PRAISON_WANDB") else "wandb",
|
||||
save_steps=100 if os.getenv("PRAISON_WANDB") else None,
|
||||
run_name=os.getenv("PRAISON_WANDB_RUN_NAME", "praisonai-train") if os.getenv("PRAISON_WANDB") else None,
|
||||
remove_unused_columns=False,
|
||||
)
|
||||
# Since the dataset is pre-tokenized, we supply a dummy dataset_text_field.
|
||||
trainer = SFTTrainer(
|
||||
model=self.model,
|
||||
tokenizer=self.tokenizer,
|
||||
train_dataset=dataset,
|
||||
dataset_text_field=self.config["dataset_text_field"],
|
||||
tokenizer=self.hf_tokenizer,
|
||||
train_dataset=tokenized_dataset,
|
||||
dataset_text_field="input_ids", # Dummy field since data is numeric
|
||||
max_seq_length=self.config["max_seq_length"],
|
||||
dataset_num_proc=self.config["dataset_num_proc"],
|
||||
packing=self.config["packing"],
|
||||
args=TrainingArguments(
|
||||
per_device_train_batch_size=self.config["per_device_train_batch_size"],
|
||||
gradient_accumulation_steps=self.config["gradient_accumulation_steps"],
|
||||
warmup_steps=self.config["warmup_steps"],
|
||||
num_train_epochs=self.config["num_train_epochs"],
|
||||
max_steps=self.config["max_steps"],
|
||||
learning_rate=self.config["learning_rate"],
|
||||
fp16=not is_bfloat16_supported(),
|
||||
bf16=is_bfloat16_supported(),
|
||||
logging_steps=self.config["logging_steps"],
|
||||
optim=self.config["optim"],
|
||||
weight_decay=self.config["weight_decay"],
|
||||
lr_scheduler_type=self.config["lr_scheduler_type"],
|
||||
seed=self.config["seed"],
|
||||
output_dir=self.config["output_dir"],
|
||||
),
|
||||
dataset_num_proc=1, # Use a single process to avoid pickling issues
|
||||
packing=False,
|
||||
args=training_args,
|
||||
)
|
||||
from unsloth.chat_templates import train_on_responses_only
|
||||
trainer = train_on_responses_only(
|
||||
trainer,
|
||||
instruction_part="<|start_header_id|>user<|end_header_id|>\n\n",
|
||||
response_part="<|start_header_id|>assistant<|end_header_id|>\n\n",
|
||||
)
|
||||
print("DEBUG: Beginning trainer.train() ...")
|
||||
trainer.train()
|
||||
self.model.save_pretrained("lora_model") # Local saving
|
||||
self.tokenizer.save_pretrained("lora_model")
|
||||
print("DEBUG: Training complete. Saving model and tokenizer locally...")
|
||||
self.model.save_pretrained("lora_model")
|
||||
self.hf_tokenizer.save_pretrained("lora_model")
|
||||
print("DEBUG: Saved model and tokenizer to 'lora_model'.")
|
||||
|
||||
def inference(self, instruction, input_text):
|
||||
FastLanguageModel.for_inference(self.model)
|
||||
alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
|
||||
messages = [{"role": "user", "content": f"{instruction}\n\nInput: {input_text}"}]
|
||||
inputs = self.hf_tokenizer.apply_chat_template(
|
||||
messages,
|
||||
tokenize=True,
|
||||
add_generation_prompt=True,
|
||||
return_tensors="pt"
|
||||
).to("cuda")
|
||||
outputs = self.model.generate(
|
||||
input_ids=inputs,
|
||||
max_new_tokens=64,
|
||||
use_cache=True,
|
||||
temperature=1.5,
|
||||
min_p=0.1
|
||||
)
|
||||
print("DEBUG: Inference output:", self.hf_tokenizer.batch_decode(outputs))
|
||||
|
||||
### Instruction:
|
||||
{}
|
||||
|
||||
### Input:
|
||||
{}
|
||||
|
||||
### Response:
|
||||
{}"""
|
||||
inputs = self.tokenizer([alpaca_prompt.format(instruction, input_text, "")], return_tensors="pt").to("cuda")
|
||||
outputs = self.model.generate(**inputs, max_new_tokens=64, use_cache=True)
|
||||
print(self.tokenizer.batch_decode(outputs))
|
||||
|
||||
def load_model(self):
|
||||
"""Loads the model and tokenizer using the FastLanguageModel library."""
|
||||
from unsloth import FastLanguageModel
|
||||
model, tokenizer = FastLanguageModel.from_pretrained(
|
||||
model_name=self.config["output_dir"],
|
||||
@@ -177,56 +292,233 @@ class train:
|
||||
shutil.rmtree(self.config["hf_model_name"])
|
||||
self.model.push_to_hub_merged(
|
||||
self.config["hf_model_name"],
|
||||
self.tokenizer,
|
||||
self.hf_tokenizer,
|
||||
save_method="merged_16bit",
|
||||
token=os.getenv('HF_TOKEN')
|
||||
token=os.getenv("HF_TOKEN")
|
||||
)
|
||||
|
||||
def push_model_gguf(self):
|
||||
self.model.push_to_hub_gguf(
|
||||
self.config["hf_model_name"],
|
||||
self.tokenizer,
|
||||
self.hf_tokenizer,
|
||||
quantization_method=self.config["quantization_method"],
|
||||
token=os.getenv('HF_TOKEN')
|
||||
token=os.getenv("HF_TOKEN")
|
||||
)
|
||||
|
||||
|
||||
def save_model_gguf(self):
|
||||
self.model.save_pretrained_gguf(
|
||||
self.config["hf_model_name"],
|
||||
self.tokenizer,
|
||||
self.hf_tokenizer,
|
||||
quantization_method="q4_k_m"
|
||||
)
|
||||
|
||||
def prepare_modelfile_content(self):
|
||||
output_model = self.config["hf_model_name"]
|
||||
gguf_path = f"{output_model}/unsloth.Q4_K_M.gguf"
|
||||
model_name = self.config["model_name"].lower()
|
||||
# Mapping from model name keywords to their default TEMPLATE and stop tokens (and optional SYSTEM/num_ctx)
|
||||
mapping = {
|
||||
"llama": {
|
||||
"template": """<|start_header_id|>system<|end_header_id|>
|
||||
Cutting Knowledge Date: December 2023
|
||||
{{ if .System }}{{ .System }}
|
||||
{{- end }}
|
||||
{{- if .Tools }}When you receive a tool call response, use the output to format an answer to the orginal user question.
|
||||
You are a helpful assistant with tool calling capabilities.
|
||||
{{- end }}<|eot_id|>
|
||||
{{- range $i, $_ := .Messages }}
|
||||
{{- $last := eq (len (slice $.Messages $i)) 1 }}
|
||||
{{- if eq .Role "user" }}<|start_header_id|>user<|end_header_id|>
|
||||
{{- if and $.Tools $last }}
|
||||
Given the following functions, please respond with a JSON for a function call with its proper arguments that best answers the given prompt.
|
||||
Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}. Do not use variables.
|
||||
{{ range $.Tools }}
|
||||
{{- . }}
|
||||
{{ end }}
|
||||
{{ .Content }}<|eot_id|>
|
||||
{{- else }}
|
||||
{{ .Content }}<|eot_id|>
|
||||
{{- end }}{{ if $last }}<|start_header_id|>assistant<|end_header_id|>
|
||||
{{ end }}
|
||||
{{- else if eq .Role "assistant" }}<|start_header_id|>assistant<|end_header_id|>
|
||||
{{- if .ToolCalls }}
|
||||
{{ range .ToolCalls }}
|
||||
{"name": "{{ .Function.Name }}", "parameters": {{ .Function.Arguments }}}{{ end }}
|
||||
{{- else }}
|
||||
{{ .Content }}
|
||||
{{- end }}{{ if not $last }}<|eot_id|>{{ end }}
|
||||
{{- else if eq .Role "tool" }}<|start_header_id|>ipython<|end_header_id|>
|
||||
{{ .Content }}<|eot_id|>{{ if $last }}<|start_header_id|>assistant<|end_header_id|>
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}""",
|
||||
"stop_tokens": ["<|start_header_id|>", "<|end_header_id|>", "<|eot_id|>"]
|
||||
},
|
||||
"qwen": {
|
||||
"template": """{{- if .Suffix }}<|fim_prefix|>{{ .Prompt }}<|fim_suffix|>{{ .Suffix }}<|fim_middle|>
|
||||
{{- else if .Messages }}
|
||||
{{- if or .System .Tools }}<|im_start|>system
|
||||
{{- if .System }}
|
||||
{{ .System }}
|
||||
{{- end }}
|
||||
{{- if .Tools }}
|
||||
# Tools
|
||||
You may call one or more functions to assist with the user query.
|
||||
You are provided with function signatures within <tools></tools> XML tags:
|
||||
<tools>
|
||||
{{- range .Tools }}
|
||||
{"type": "function", "function": {{ .Function }}}
|
||||
{{- end }}
|
||||
</tools>
|
||||
For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:
|
||||
<tool_call>
|
||||
{"name": <function-name>, "arguments": <args-json-object>}
|
||||
</tool_call>
|
||||
{{- end }}<|im_end|>
|
||||
{{ end }}
|
||||
{{- range $i, $_ := .Messages }}
|
||||
{{- $last := eq (len (slice $.Messages $i)) 1 -}}
|
||||
{{- if eq .Role "user" }}<|im_start|>user
|
||||
{{ .Content }}<|im_end|>
|
||||
{{ else if eq .Role "assistant" }}<|im_start|>assistant
|
||||
{{ if .Content }}{{ .Content }}
|
||||
{{- else if .ToolCalls }}<tool_call>
|
||||
{{ range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}}
|
||||
{{ end }}</tool_call>
|
||||
{{- end }}{{ if not $last }}<|im_end|>
|
||||
{{ end }}
|
||||
{{- else if eq .Role "tool" }}<|im_start|>user
|
||||
<tool_response>
|
||||
{{ .Content }}
|
||||
</tool_response><|im_end|>
|
||||
{{ end }}
|
||||
{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if .System }}<|im_start|>system
|
||||
{{ .System }}<|im_end|>
|
||||
{{ end }}{{ if .Prompt }}<|im_start|>user
|
||||
{{ .Prompt }}<|im_end|>
|
||||
{{ end }}<|im_start|>assistant
|
||||
{{ end }}{{ .Response }}{{ if .Response }}<|im_end|>{{ end }}""",
|
||||
"system": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant.",
|
||||
"num_ctx": 32768,
|
||||
"stop_tokens": ["<|endoftext|>"]
|
||||
},
|
||||
"mistral": {
|
||||
"template": "[INST] {{ if .System }}{{ .System }} {{ end }}{{ .Prompt }} [/INST]",
|
||||
"stop_tokens": ["[INST]", "[/INST]"]
|
||||
},
|
||||
"phi": {
|
||||
"template": """{{- range $i, $_ := .Messages }}
|
||||
{{- $last := eq (len (slice $.Messages $i)) 1 -}}
|
||||
<|im_start|>{{ .Role }}<|im_sep|>
|
||||
{{ .Content }}{{ if not $last }}<|im_end|>
|
||||
{{ end }}
|
||||
{{- if and (ne .Role "assistant") $last }}<|im_end|>
|
||||
<|im_start|>assistant<|im_sep|>
|
||||
{{ end }}
|
||||
{{- end }}""",
|
||||
"stop_tokens": ["<|im_start|>", "<|im_end|>", "<|im_sep|>"]
|
||||
},
|
||||
"deepseek": {
|
||||
"template": """{{- if .System }}{{ .System }}{{ end }}
|
||||
{{- range $i, $_ := .Messages }}
|
||||
{{- $last := eq (len (slice $.Messages $i)) 1}}
|
||||
{{- if eq .Role "user" }}<|User|>{{ .Content }}
|
||||
{{- else if eq .Role "assistant" }}<|Assistant|>{{ .Content }}{{- if not $last }}<|end▁of▁sentence|>{{- end }}
|
||||
{{- end }}
|
||||
{{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}
|
||||
{{- end }}""",
|
||||
"stop_tokens": ["<|begin▁of▁sentence|>", "<|end▁of▁sentence|>", "<|User|>", "<|Assistant|>"]
|
||||
},
|
||||
"llava": {
|
||||
"template": """{{- if .Suffix }}<|fim_prefix|>{{ .Prompt }}<|fim_suffix|>{{ .Suffix }}<|fim_middle|>
|
||||
{{- else if .Messages }}
|
||||
{{- if or .System .Tools }}<|im_start|>system
|
||||
{{- if .System }}
|
||||
{{ .System }}
|
||||
{{- end }}
|
||||
{{- if .Tools }}
|
||||
# Tools
|
||||
You may call one or more functions to assist with the user query.
|
||||
You are provided with function signatures within <tools></tools> XML tags:
|
||||
<tools>
|
||||
{{- range .Tools }}
|
||||
{"type": "function", "function": {{ .Function }}}
|
||||
{{- end }}
|
||||
</tools>
|
||||
For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:
|
||||
<tool_call>
|
||||
{"name": <function-name>, "arguments": <args-json-object>}
|
||||
</tool_call>
|
||||
{{- end }}<|im_end|>
|
||||
{{ end }}
|
||||
{{- range $i, $_ := .Messages }}
|
||||
{{- $last := eq (len (slice $.Messages $i)) 1 -}}
|
||||
{{- if eq .Role "user" }}<|im_start|>user
|
||||
{{ .Content }}<|im_end|>
|
||||
{{ else if eq .Role "assistant" }}<|im_start|>assistant
|
||||
{{ if .Content }}{{ .Content }}
|
||||
{{- else if .ToolCalls }}<tool_call>
|
||||
{{ range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}}
|
||||
{{ end }}</tool_call>
|
||||
{{- end }}{{ if not $last }}<|im_end|>
|
||||
{{ end }}
|
||||
{{- else if eq .Role "tool" }}<|im_start|>user
|
||||
<tool_response>
|
||||
{{ .Content }}
|
||||
</tool_response><|im_end|>
|
||||
{{ end }}
|
||||
{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if .System }}<|im_start|>system
|
||||
{{ .System }}<|im_end|>
|
||||
{{ end }}{{ if .Prompt }}<|im_start|>user
|
||||
{{ .Prompt }}<|im_end|>
|
||||
{{ end }}<|im_start|>assistant
|
||||
{{ end }}{{ .Response }}{{ if .Response }}<|im_end|>{{ end }}""",
|
||||
"stop_tokens": ["</s>", "USER:", "ASSSISTANT:"]
|
||||
}
|
||||
}
|
||||
# Select mapping by checking if any key is in the model_name.
|
||||
chosen = None
|
||||
for key, settings in mapping.items():
|
||||
if key in model_name:
|
||||
chosen = settings
|
||||
break
|
||||
if chosen is None:
|
||||
# Fallback default
|
||||
chosen = {
|
||||
"template": """{{ if .System }}<|start_header_id|>system<|end_header_id|>
|
||||
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
|
||||
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
|
||||
{{ .Response }}<|eot_id|>""",
|
||||
"stop_tokens": ["<|start_header_id|>", "<|end_header_id|>", "<|eot_id|>"]
|
||||
}
|
||||
# Build the stop parameter lines.
|
||||
stop_params = "\n".join([f"PARAMETER stop {token}" for token in chosen["stop_tokens"]])
|
||||
# Optionally include a SYSTEM line and num_ctx if defined in the mapping.
|
||||
system_line = ""
|
||||
if "system" in chosen:
|
||||
system_line = f"SYSTEM {chosen['system']}\n"
|
||||
num_ctx_line = ""
|
||||
if "num_ctx" in chosen:
|
||||
num_ctx_line = f"PARAMETER num_ctx {chosen['num_ctx']}\n"
|
||||
# Assemble and return the modelfile content.
|
||||
return f"""FROM {output_model}
|
||||
TEMPLATE \"\"\"{chosen['template']}\"\"\"
|
||||
{system_line}{num_ctx_line}{stop_params}
|
||||
"""
|
||||
|
||||
# Check if the GGUF file exists. If not, generate it ## TODO Multiple Quantisation other than Q4_K_M.gguf
|
||||
if not os.path.exists(gguf_path):
|
||||
self.model, self.tokenizer = self.load_model()
|
||||
self.save_model_gguf()
|
||||
return f"""FROM {output_model}/unsloth.Q4_K_M.gguf
|
||||
|
||||
TEMPLATE \"\"\"Below are some instructions that describe some tasks. Write responses that appropriately complete each request.{{{{ if .Prompt }}}}
|
||||
|
||||
### Instruction:
|
||||
{{{{ .Prompt }}}}
|
||||
|
||||
{{{{ end }}}}### Response:
|
||||
{{{{ .Response }}}}\"\"\"
|
||||
|
||||
PARAMETER stop ""
|
||||
PARAMETER stop ""
|
||||
PARAMETER stop ""
|
||||
PARAMETER stop ""
|
||||
PARAMETER stop "<|reserved_special_token_"
|
||||
"""
|
||||
|
||||
def create_and_push_ollama_model(self):
|
||||
modelfile_content = self.prepare_modelfile_content()
|
||||
with open('Modelfile', 'w') as file:
|
||||
with open("Modelfile", "w") as file:
|
||||
file.write(modelfile_content)
|
||||
|
||||
subprocess.run(["ollama", "serve"])
|
||||
subprocess.run(["ollama", "create", f"{self.config['ollama_model']}:{self.config['model_parameters']}", "-f", "Modelfile"])
|
||||
subprocess.run(["ollama", "push", f"{self.config['ollama_model']}:{self.config['model_parameters']}"])
|
||||
@@ -235,42 +527,36 @@ PARAMETER stop "<|reserved_special_token_"
|
||||
self.print_system_info()
|
||||
self.check_gpu()
|
||||
self.check_ram()
|
||||
# self.install_packages()
|
||||
if self.config.get("train", "true").lower() == "true":
|
||||
self.prepare_model()
|
||||
self.train_model()
|
||||
|
||||
if self.config.get("huggingface_save", "true").lower() == "true":
|
||||
# self.model, self.tokenizer = self.load_model()
|
||||
self.save_model_merged()
|
||||
|
||||
if self.config.get("huggingface_save_gguf", "true").lower() == "true":
|
||||
# self.model, self.tokenizer = self.load_model()
|
||||
self.push_model_gguf()
|
||||
|
||||
# if self.config.get("save_gguf", "true").lower() == "true": ## TODO
|
||||
# self.model, self.tokenizer = self.load_model()
|
||||
# self.save_model_gguf()
|
||||
|
||||
# if self.config.get("save_merged", "true").lower() == "true": ## TODO
|
||||
# self.model, self.tokenizer = self.load_model()
|
||||
# self.save_model_merged()
|
||||
|
||||
if self.config.get("ollama_save", "true").lower() == "true":
|
||||
self.create_and_push_ollama_model()
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='PraisonAI Training Script')
|
||||
parser.add_argument('command', choices=['train'], help='Command to execute')
|
||||
parser.add_argument('--config', default='config.yaml', help='Path to configuration file')
|
||||
parser = argparse.ArgumentParser(description="PraisonAI Training Script")
|
||||
parser.add_argument("command", choices=["train"], help="Command to execute")
|
||||
parser.add_argument("--config", default="config.yaml", help="Path to configuration file")
|
||||
parser.add_argument("--model", type=str, help="Model name")
|
||||
parser.add_argument("--hf", type=str, help="Hugging Face model name")
|
||||
parser.add_argument("--ollama", type=str, help="Ollama model name")
|
||||
parser.add_argument("--dataset", type=str, help="Dataset name for training")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == 'train':
|
||||
ai = train(config_path=args.config)
|
||||
ai.run()
|
||||
if args.command == "train":
|
||||
# Check if any command line args are provided that would override config
|
||||
if any([args.model, args.hf, args.ollama, args.dataset]):
|
||||
# Use CLI provided arguments
|
||||
trainer_obj = TrainModel(config_path=args.config)
|
||||
else:
|
||||
# Use existing config.yaml without modification
|
||||
trainer_obj = TrainModel("config.yaml")
|
||||
trainer_obj.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.54"
|
||||
version = "2.0.71"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
|
||||
readme = "README.md"
|
||||
license = ""
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.0.45",
|
||||
"praisonaiagents>=0.0.61",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
@@ -84,7 +84,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.7", "crewai"]
|
||||
|
||||
[tool.poetry]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.54"
|
||||
version = "2.0.71"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration."
|
||||
authors = ["Mervin Praison"]
|
||||
license = ""
|
||||
@@ -102,7 +102,7 @@ python = ">=3.10,<3.13"
|
||||
rich = ">=13.7"
|
||||
markdown = ">=3.5"
|
||||
pyparsing = ">=3.0.0"
|
||||
praisonaiagents = ">=0.0.45"
|
||||
praisonaiagents = ">=0.0.61"
|
||||
python-dotenv = ">=0.19.0"
|
||||
instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
1. Make minimal code changes as possible
|
||||
2. if you are creating function, make sure to name it in more easy, user friendly , optimised manner.
|
||||
3. Never copy the exact code if presented with a code from other location or file or codebase, just make it optimised
|
||||
4. Always Follow the principle LESS IS MORE
|
||||
5. Make it minimal change as possible
|
||||
6. Firstly try not to make any modification to the existing code as possible
|
||||
7. Only modify the existing code if its highly required, without that if it cant be done, then add new code section.
|
||||
8. If you are adding new code, make sure to add it in a way that it can be easily integrated with the existing codebase.
|
||||
|
||||
|
||||
Below is a **detailed technical overview** of the issues that have been coming up in the workflow execution (specifically around loops, resetting tasks, and continuing on to subsequent tasks). It includes:
|
||||
|
||||
1. **How the workflow currently flows**
|
||||
2. **What logic marks a task as “completed”**
|
||||
3. **What issues arose in `loop` tasks**
|
||||
4. **Why the workflow can end up “stuck” or “looping indefinitely”**
|
||||
|
||||
---
|
||||
|
||||
## 1. Overall Workflow Flow
|
||||
|
||||
### a. Building relationships among tasks
|
||||
|
||||
- At startup, the code iterates through all `tasks`.
|
||||
- For each `task`:
|
||||
- It looks at `task.next_tasks`, and for each `next_task_name`:
|
||||
- Finds the corresponding `Task` object
|
||||
- Appends the current task’s name to the found `next_task`'s `previous_tasks` list.
|
||||
- This means if Task A has `next_tasks=["B"]`, then Task B’s `previous_tasks` will include `"A"`.
|
||||
|
||||
### b. Finding and starting with a “start task”
|
||||
|
||||
- The workflow code tries to locate a task with `is_start=True`.
|
||||
- If no such task is found, it uses the first item in the tasks dictionary instead.
|
||||
- That “start task” is what the workflow tries to run first.
|
||||
|
||||
### c. Execution loop in the method (e.g., `workflow()` or `aworkflow()`)
|
||||
|
||||
- There is a `while current_task:` loop that processes tasks in sequence, or conditionally, based on `task.condition`.
|
||||
- Each time a task runs (if non-loop), it yields the `task_id` or triggers an agent to run. Once the agent finishes (with or without a final result), the workflow picks up again to see what to do next:
|
||||
- If the `task` is a `loop` type, the code tries to create or manage sub-tasks for each row/line in an “input_file.”
|
||||
- If the `task` is a normal (“decision” or “task” or “some-other-type”), it just executes once, sets `status="completed"`, and the code moves on.
|
||||
|
||||
### d. Condition-based branching
|
||||
|
||||
- If a task has a result that includes a “decision” (like `{"decision":"more"}` or `"done"`), the code checks `task.condition`. For example:
|
||||
```python
|
||||
condition = {
|
||||
"more": "generate_task",
|
||||
"done": "evaluate_total_questions"
|
||||
}
|
||||
```
|
||||
- If the result’s decision is `"done"`, it jumps to the task named `"evaluate_total_questions"`.
|
||||
- If the result’s decision is `"more"`, it jumps right back to `"generate_task"`.
|
||||
- If no condition matches, it can fallback to the first item in `task.next_tasks`.
|
||||
|
||||
### e. Marking tasks as “completed”
|
||||
|
||||
- After a task’s execution (like a typical “non-loop” task), the code sets `task.status = "completed"`.
|
||||
- Then the code has a snippet that says:
|
||||
```python
|
||||
if self.tasks[task_id].status == "completed":
|
||||
# Possibly reset to "not started" so we can re-run if needed
|
||||
```
|
||||
- By default, the system tries to “reset” tasks to `"not started"`, **unless** it is a loop task or a subtask of a loop.
|
||||
|
||||
---
|
||||
|
||||
## 2. How a “completed” task is marked
|
||||
|
||||
Generally, tasks are marked `status="completed"` in two primary ways:
|
||||
|
||||
1. **Non-Loop Execution**
|
||||
A normal task (like a “decision” or “task”) is executed once the code calls the agent, the agent returns a final result, and the system sets `task.status = "completed"`.
|
||||
2. **Loop Execution**
|
||||
A loop-type task is *programmatically* set to `status="completed"` when all of its sub-tasks have finished. That is:
|
||||
- The code checks: “Have all child tasks of this loop finished?”
|
||||
- If `True`, the loop task is set to `completed`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Issues Specifically in `loop` Tasks
|
||||
|
||||
### a. Re-Entering the Loop
|
||||
|
||||
- Before, the same snippet that “resets completed tasks to ‘not started’ so they can re-run if needed” **also** tried to reset loop tasks or their subtasks.
|
||||
- If a loop task got reset to `"not started"`, the code would eventually pick it back up again, leading to repeated creation of sub-tasks (or repeated attempts to re-run them).
|
||||
- This caused an **infinite loop** or repeating the same steps in the workflow, never truly exiting the loop stage.
|
||||
|
||||
### b. Subtasks Not Marked or Overwritten
|
||||
|
||||
- Another tricky scenario: If sub-tasks themselves got reset, the parent loop would see them as “not started” again, and might wait for them to “complete,” or might re-run them. That can lead to indefinite re-running of sub-tasks.
|
||||
|
||||
### c. Not Proceeding to Next (e.g., “upload_to_huggingface”)
|
||||
|
||||
- If the loop kept “restarting,” the workflow never ended up hitting the next tasks. For example, if your workflow is:
|
||||
1. `generate_task`
|
||||
2. `evaluate_total_questions`
|
||||
3. `generate_cot` (loop)
|
||||
4. `upload_to_huggingface`
|
||||
- The system might get stuck in step #3 indefinitely (the sub-tasks keep getting reset, so it never actually transitions to step #4).
|
||||
|
||||
### d. Condition Logic vs. Next Tasks
|
||||
|
||||
- Another subtlety: If the loop tasks had a `condition` that pointed them back to a prior step, it might cause unintentional re-entry. Typically, you only want loop tasks to proceed once, **unless** you explicitly want to re-visit. But if it’s a data ingestion process, you usually want to do it once, then move on to the next step.
|
||||
|
||||
---
|
||||
|
||||
## 4. Why the System Can End Up Stuck or “Looping Indefinitely”
|
||||
|
||||
1. **Reset Mechanism**
|
||||
- The code tries to “reset tasks to ‘not started’ once they complete,” so they can be re-run in some dynamic multi-run scenario.
|
||||
- But that same logic can cause loop tasks to revert back to “not started” the moment they end. The system sees “Oh, a task is ‘not started’? Let’s run it!” and you’re in a cycle.
|
||||
|
||||
2. **No Condition for Exit**
|
||||
- If the loop has a condition that leads back to a prior step (like `"more" -> generate_cot`), it can keep re-running.
|
||||
|
||||
3. **Subtasks Not Marked**
|
||||
- If the subtask or the loop tries to “reactivate” each other, it never exits.
|
||||
|
||||
---
|
||||
|
||||
## Summary of the “Core Problem”
|
||||
|
||||
1. We want to keep the resetting mechanism for **non-loop tasks** – because in some advanced workflows, we like re-running them from a different path or after some condition.
|
||||
2. But we want **loop tasks** to remain `"completed"` once all sub-tasks are done, so the code can seamlessly proceed to the next major step.
|
||||
3. Before the fix, loop tasks or their sub-tasks got reset. This triggered the system to re-enter the loop, re-run the sub-tasks, etc., causing an infinite loop and preventing the workflow from reaching tasks like “upload_to_huggingface.”
|
||||
|
||||
---
|
||||
|
||||
## Technical Highlights to Pass On
|
||||
|
||||
- **In the reset snippet**:
|
||||
```python
|
||||
if self.tasks[task_id].status == "completed":
|
||||
# never reset if loop or subtask-of-loop
|
||||
# else reset to "not started"
|
||||
```
|
||||
This is crucial to skipping re-runs on loop tasks.
|
||||
- **Ensure** that once a loop’s sub-tasks are all “completed,” the loop’s status is set to “completed,” and it transitions to the next major tasks (like `upload_to_huggingface`).
|
||||
- **Check** if the loop’s condition is correct. If you want a single pass, do not implement a condition that leads back to the same loop.
|
||||
- Also, you can check you do not have “overlapping conditions” that cause re-entry.
|
||||
|
||||
---
|
||||
|
||||
### Conclusion
|
||||
|
||||
**Hence,** the main challenge is that the reset logic (meant to let normal tasks be re-run) conflicts with a loop task’s one-pass usage. Once you avoid resetting the loop tasks or sub-tasks, you can finish them once, mark them “completed,” and properly proceed to the next stage.
|
||||
|
||||
Dont remove any logging or debug statements, as it will help you to understand the flow of the code.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 335 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user