Compare commits

...
48 Commits
Author SHA1 Message Date
Mervin Praison ef7fa66e33 Merge pull request #324 from MervinPraison/develop
Update PraisonAI to version 2.0.57 and enhance documentation
2025-01-23 06:06:43 +00:00
MervinPraison 1659ed61bc Update PraisonAI to version 2.0.57 and enhance documentation
- Bumped PraisonAI version from 2.0.56 to 2.0.57 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonaiagents` dependency version from `0.0.49` to `0.0.50` across relevant files for improved functionality.
- Added a new `docker-compose.yml` file and multiple Dockerfiles for different services (UI, chat, development) to streamline deployment.
- Enhanced the README.md with new sections on AI agents flow, tools, memory, and various processing types, improving clarity and usability.
- Introduced a new test script `cl-test.py` for validating chat functionalities with the Gemini API.

These changes improve the overall functionality, usability, and deployment processes of the PraisonAI framework.
2025-01-23 06:06:23 +00:00
Mervin Praison b8939ef439 Merge pull request #323 from MervinPraison/develop
adding chat with pdf
2025-01-22 18:37:48 +00:00
MervinPraison 4bada9e5fc adding chat with pdf 2025-01-22 18:37:27 +00:00
Mervin Praison 51c4cb00b0 Merge pull request #322 from MervinPraison/develop
updating docs
2025-01-22 18:32:20 +00:00
MervinPraison ad96549ea3 updating docs 2025-01-22 18:32:03 +00:00
Mervin Praison 183d10d7cc Merge pull request #321 from MervinPraison/develop
Develop
2025-01-22 18:29:04 +00:00
MervinPraison bce1559ab5 docs update 2025-01-22 18:28:46 +00:00
MervinPraison 6f3fb87ba3 Update README and local development documentation for improved clarity and logging instructions
- Revised section headings in README.md to number the agent categories for better organization.
- Added logging configuration instructions to the local-development.mdx file, detailing how to set log levels for both standard and advanced logging.
- Removed outdated logging instructions from README.md to streamline the documentation.

These changes enhance the clarity of the documentation and provide users with essential logging setup information for local development.
2025-01-22 18:24:24 +00:00
Mervin Praison e7f6b2df67 Merge pull request #320 from MervinPraison/develop
Update README and agent initialization for enhanced clarity and funct…
2025-01-22 18:07:29 +00:00
MervinPraison 08d72eeb80 Update README and agent initialization for enhanced clarity and functionality
- Revised the README.md to better describe PraisonAI as a production-ready Multi-AI Agents framework, emphasizing its capabilities in automating tasks and problem-solving.
- Updated the list of features to include new agent types and functionalities, such as Code Interpreter Agents and Async & Parallel Processing.
- Simplified the agent initialization examples in the README, providing clearer instructions for users to create and run agents.
- Modified the agent client initialization in main.py to handle missing API keys more gracefully.
- Added "developers/local-development" to mint.json for improved documentation structure.

These changes enhance the user experience by providing clearer documentation and improving the robustness of agent initialization.
2025-01-22 18:07:15 +00:00
Mervin Praison 11aefae90f Merge pull request #319 from MervinPraison/develop
Enhance Streamlit UIs and Add New Model Integrations
2025-01-22 13:07:45 +00:00
MervinPraison 10d5158d27 Enhance Streamlit UIs and Add New Model Integrations
- Updated `mint.json` to include new Streamlit UIs for Deepseek, Gemini, and Ollama models, improving model accessibility.
- Expanded documentation in `models.mdx` and `google.mdx` to provide detailed setup instructions for integrating OpenAI, Litellm, and Gemini models.
- Introduced new example scripts for Gemini and Ollama Streamlit applications, showcasing interactive chat capabilities.
- Added comprehensive features and prerequisites sections in the new UI documentation to guide users in setting up their environments.

These changes enhance the usability and functionality of the PraisonAI framework, particularly in model integration and user interface development.
2025-01-22 13:07:31 +00:00
Mervin Praison 1d8b814fcd Merge pull request #318 from MervinPraison/develop
Update PraisonAI to version 2.0.56 and enhance agent functionality
2025-01-22 10:46:35 +00:00
MervinPraison 6e8a5b98a8 Update PraisonAI to version 2.0.56 and enhance agent functionality
- Bumped PraisonAI version from 2.0.55 to 2.0.56 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.46` to `0.0.49` across relevant files for improved functionality.
- Introduced new agent examples for Google Gemini and Deepseek models, enhancing the framework's capabilities.
- Enhanced logging configurations to suppress unnecessary output and improve clarity during execution.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in agent management and logging clarity.
2025-01-22 10:46:18 +00:00
Mervin Praison 59d0ff8c95 Merge pull request #317 from MervinPraison/develop
Refactor deepseek agent implementation and remove unused files
2025-01-21 19:02:39 +00:00
MervinPraison b2109faa06 Refactor deepseek agent implementation and remove unused files
- Simplified the deepseek agent setup by removing the previous configuration and task definitions, replacing them with a more streamlined agent initialization.
- Updated the agent's instructions for clarity and direct usage.
- Deleted the unused `small.pdf` file to clean up the repository.
- Added "deepseek" model to the list of available models in `mint.json` for improved model management.

These changes enhance the usability and clarity of the deepseek agent within the PraisonAI framework.
2025-01-21 19:02:25 +00:00
Mervin Praison 024eaed456 Merge pull request #316 from MervinPraison/develop
Develop
2025-01-21 17:51:15 +00:00
MervinPraison 4fd3a572cf Update PraisonAI to version 2.0.55 and adjust dependencies
- Bumped PraisonAI version from 2.0.54 to 2.0.55 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.45` to `0.0.46` across relevant files for improved functionality.
- Adjusted deployment scripts and documentation to ensure compatibility with the new version.

These changes enhance the overall functionality and usability of the PraisonAI framework, particularly in dependency management and deployment processes.
2025-01-21 17:50:53 +00:00
MervinPraison baaf8b6256 Update version to 0.0.46 and enhance memory feature checks
- Bumped the version of the `praisonaiagents` package from 0.0.45 to 0.0.46 in `pyproject.toml` and `uv.lock` to reflect the latest updates.
- Added import checks for memory features in the `Agent`, `PraisonAIAgents`, and `Task` classes to ensure proper handling of memory dependencies.
- Removed the obsolete `Memory` import from the `__init__.py` file to streamline the codebase.

These changes improve the robustness of the PraisonAI framework by ensuring that memory features are only utilized when the necessary dependencies are installed.
2025-01-21 16:47:31 +00:00
Mervin Praison fe4550d2bc Merge pull request #315 from MervinPraison/develop
2.0.54
2025-01-21 15:01:57 +00:00
MervinPraison db09a94425 Update PraisonAI to version 2.0.54 and enhance agent functionality
- Bumped PraisonAI version from 2.0.53 to 2.0.54 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.44` to `0.0.45` across relevant files for improved functionality.
- Removed the obsolete `knowledge-embedding-agents.py` file and introduced a new `vector-db-agents.py` file to enhance knowledge retrieval capabilities.
- Added new documentation for RAG (Retrieval Augmented Generation) agents, detailing their configuration and usage in `docs/features/rag.mdx`.
- Updated deployment scripts to ensure compatibility with the new version and improved agent functionalities.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in knowledge management and retrieval capabilities.
2025-01-21 15:01:12 +00:00
MervinPraison 2db36dc932 Enhance Knowledge Agent Configuration and Update Version
- Updated the Knowledge Agent configuration to include a new versioning system and improved vector store settings.
- Changed the collection name from "custom_knowledge" to "praison" for consistency across files.
- Added user_id parameter to the Knowledge Agent for better user tracking.
- Enhanced the embedding database configuration to support dynamic context management.
- Bumped the version of the `praisonaiagents` package from 0.0.44 to 0.0.45 in `pyproject.toml` to reflect these updates.

These changes improve the functionality and usability of the Knowledge Agent within the PraisonAI framework, particularly in knowledge management and retrieval capabilities.
2025-01-21 13:09:41 +00:00
Mervin Praison 8c0e4277a4 Merge pull request #313 from MervinPraison/develop
Update PraisonAI to version 2.0.53 and enhance agent functionality
2025-01-20 10:04:38 +00:00
MervinPraison 41448617d5 Update PraisonAI to version 2.0.53 and enhance agent functionality
- Bumped PraisonAI version from 2.0.52 to 2.0.53 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.43` to `0.0.44` across relevant files for improved functionality.
- Enhanced the `PraisonAIAgents` class to include a `max_iter` parameter, allowing for more control over agent iterations.
- Added new tasks to `agents/tasks.csv` to expand the capabilities of the agents in handling various writing tasks.
- Updated documentation to reflect changes in agent functionality and new task examples.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in task execution and agent capabilities.
2025-01-20 10:04:20 +00:00
Mervin Praison 49ea23c676 Merge pull request #312 from MervinPraison/develop
Introducing Repetitive Agents
2025-01-20 07:18:19 +00:00
MervinPraison bb0dc63680 Update PraisonAI to version 2.0.52 and enhance repetitive agents functionality
- Bumped PraisonAI version from 2.0.51 to 2.0.52 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.42` to `0.0.43` across relevant files for improved functionality.
- Introduced new files for repetitive agents in `agents/repetitive-agents.py` and `examples/concepts/repetitive-agents.py`, enabling automated task loops.
- Enhanced documentation with a new section on repetitive agents in `docs/features/repetitive.mdx` and updated `mint.json` to include the new feature.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in handling repetitive tasks and enhancing agent capabilities.
2025-01-20 07:17:43 +00:00
MervinPraison 7774f2c565 Add loop agent functionality and update task management in PraisonAI agents
- Introduced a new loop agent in `loop_agents.py` to create and manage a loop of tasks from a CSV file.
- Added a new file `repetitive-manual-agents.py` that implements task identification, status checking, and updating functionalities.
- Updated `process.py` to enhance task handling by allowing dynamic input files for loop tasks.
- Removed the obsolete `repeat_agents.py` file to streamline the codebase.
- Bumped the version of the `praisonaiagents` package from 0.0.42 to 0.0.43 in `pyproject.toml` and `uv.lock` to reflect these changes.

These updates improve the task execution capabilities of the PraisonAI framework, particularly in handling repetitive tasks and enhancing agent functionality.
2025-01-20 06:56:33 +00:00
MervinPraison 5533fd3476 Enhance logging and improve decision/loop task handling in PraisonAI agents
- Suppressed debug logs from the markdown parser to reduce noise in the logging output.
- Refactored decision-making logic to utilize Pydantic models for better type safety and clarity.
- Updated loop task handling to ensure proper context management and error handling.
- Introduced dynamic literal types for decision and loop tasks to enhance flexibility in task definitions.

These changes improve the overall robustness and usability of the PraisonAI framework, particularly in task execution and logging clarity.
2025-01-19 05:58:46 +00:00
Mervin Praison 262a90a235 Merge pull request #310 from MervinPraison/develop
2.0.51
2025-01-18 06:02:35 +00:00
MervinPraison 60928dcb90 Update PraisonAI to version 2.0.51 and enhance dependencies
- Bumped PraisonAI version from 2.0.50 to 2.0.51 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.41` to `0.0.42` across relevant files for improved functionality.
- Enhanced documentation with updated installation instructions for various examples, ensuring users have access to the latest package versions.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in dependency management and documentation clarity.
2025-01-18 06:02:09 +00:00
MervinPraison c8552e1158 Update PraisonAI agents package version to 0.0.42 in pyproject.toml and uv.lock
- Bumped the version from 0.0.41 to 0.0.42 to reflect recent updates and ensure users have access to the latest features and improvements.
- This change maintains the integrity of the PraisonAI framework and prepares it for future enhancements.
2025-01-18 05:48:57 +00:00
Mervin Praison c57d7db9bb Merge pull request #309 from MervinPraison/develop
Enhance Streamlit UIs for Code Analysis and Hackathon Judging
2025-01-17 22:21:06 +00:00
MervinPraison 236abc2c83 Enhance Streamlit UIs for Code Analysis and Hackathon Judging
- Updated `mint.json` to group Streamlit pages under a new "Streamlit" section, improving organization.
- Renamed titles in `code-analysis.mdx` and `hackathon-judge.mdx` to include "Agent" for clarity.
- Added new Streamlit UI files: `code-analysis-streamlit.mdx` and `hackathon-judge-streamlit.mdx`, providing interactive interfaces for code analysis and hackathon project evaluation.
- Each new UI includes detailed descriptions, features, quick start guides, and visual flowcharts to enhance user experience and understanding.

These changes significantly improve the usability and accessibility of the PraisonAI framework's Streamlit applications, offering users powerful tools for code and project evaluation.
2025-01-17 22:20:51 +00:00
Mervin Praison 76c5f8fe3f Merge pull request #308 from MervinPraison/develop
Add new code analysis and hackathon judge agents with Streamlit integ…
2025-01-17 19:03:12 +00:00
MervinPraison 82750020d2 Add new code analysis and hackathon judge agents with Streamlit integration
- Introduced `code-analysis-agents.py` and `code-analysis-streamlit.py` for comprehensive code evaluation, including metrics on architecture, maintainability, performance, and security.
- Added `context-agents-code.py` and `context-agents.py` for CV analysis capabilities, providing detailed scoring and recommendations.
- Implemented `hackathon-judge-agent.py` and `hackathon-judge-streamlit.py` for evaluating hackathon projects through video demonstrations, offering scores and feedback on innovation, technical complexity, and presentation quality.
- Enhanced documentation with new examples for code analysis and hackathon judging, improving user guidance and showcasing agent capabilities.
- Updated `mint.json` to include new examples, enriching the available resources for users.

These additions significantly expand the functionality of the PraisonAI framework, providing users with powerful tools for code and project evaluation.
2025-01-17 19:02:56 +00:00
Mervin Praison f49ad9fbc2 Merge pull request #306 from MervinPraison/develop
Develop
2025-01-17 17:35:18 +00:00
MervinPraison c086c60fd6 Update PraisonAI to version 2.0.50 and enhance dependencies
- Bumped PraisonAI version from 2.0.49 to 2.0.50 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.40` to `0.0.41` across relevant files for improved functionality.
- Added a new `context-agents.py` file to introduce a CV analysis agent with comprehensive evaluation capabilities.
- Modified deployment scripts to ensure compatibility with the updated package version.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in dependency management and the introduction of new agent capabilities.
2025-01-17 17:35:00 +00:00
MervinPraison 4f8f4f2036 Update package version to 0.0.41 in uv.lock
- Bumped the version of the PraisonAI agents package from 0.0.40 to 0.0.41 to reflect recent updates.
- This change ensures that the latest features and improvements are properly versioned and available for users.
2025-01-17 17:26:51 +00:00
MervinPraison 8e91c20967 Update package version to 0.0.41 in pyproject.toml
- Bumped the version of the PraisonAI agents package from 0.0.40 to 0.0.41 to reflect recent updates.
- This change ensures that the latest features and improvements are properly versioned and available for users.

These updates maintain the integrity of the PraisonAI framework and prepare it for future enhancements.
2025-01-17 17:26:34 +00:00
MervinPraison 6f092c1507 Refactor agent context handling and improve task prompt generation
- Updated `crewai-tools-example.py` to remove unnecessary whitespace.
- Modified `agent.py` to replace `schema_json()` with `model_json_schema()` for JSON output consistency.
- Enhanced context handling in `agents.py` to avoid duplicates and improve clarity in task prompts by using lists instead of strings.
- Added support for passing content to tasks in both `start` and `astart` methods, allowing for dynamic context management.
- Improved task prompt generation in `task.py` to handle various context types, ensuring better output formatting.

These changes enhance the functionality and usability of the PraisonAI agents, particularly in context management and task execution clarity.
2025-01-17 17:25:58 +00:00
Mervin Praison 8f553d3a54 Merge pull request #305 from MervinPraison/develop
2.0.49
2025-01-17 12:24:16 +00:00
MervinPraison 2d647e25b5 Update PraisonAI to version 2.0.49 and enhance dependencies
- Bumped PraisonAI version from 2.0.48 to 2.0.49 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.39` to `0.0.40` across relevant files for improved functionality.
- Modified deployment scripts to ensure compatibility with the updated package version.
- Enhanced documentation by adding a new "Tools" section in `mint.json` and updating the title in `custom.mdx` for better clarity.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in dependency management and documentation clarity.
2025-01-17 12:23:44 +00:00
MervinPraison 039bb772f5 Update version to 0.0.40 and enhance agent functionality
- Bumped the package version in `pyproject.toml` and `uv.lock` from `0.0.39` to `0.0.40` to reflect recent updates.
- Improved the `Agent` class in `agent.py` to support both Langchain and CrewAI tools by adding checks for the presence of `run` and `_run` methods, allowing for more flexible function handling.

These changes enhance the functionality of the PraisonAI agents, ensuring compatibility with different toolsets and improving overall usability.
2025-01-17 12:13:08 +00:00
Mervin Praison 459c2f2b70 Merge pull request #304 from MervinPraison/develop
Add new examples and enhance documentation for AI agent use cases
2025-01-17 10:34:16 +00:00
MervinPraison ee59706357 Add new examples and enhance documentation for AI agent use cases
- Introduced multiple new example files for various AI agent applications, including Climate Impact, Crypto Validator, DeFi Market Maker, Medicine Protocol, Neural Architecture, Quantum Optimiser, Research Assistant, Space Mission, and Vulnerability Detection.
- Updated `mint.json` to include new examples, improving the breadth of use cases available for users.
- Enhanced the `examples.mdx` file to provide links and descriptions for the newly added examples, facilitating easier navigation and understanding of the capabilities of PraisonAI.

These changes significantly expand the documentation and practical examples available to users, showcasing the versatility of the PraisonAI framework in various domains.
2025-01-17 10:33:58 +00:00
Mervin Praison 2a51644773 Merge pull request #303 from MervinPraison/develop
Refactor documentation and enhance quickstart guide for PraisonAI
2025-01-16 11:45:30 +00:00
MervinPraison cce908fa22 Refactor documentation and enhance quickstart guide for PraisonAI
- Removed unnecessary note from the introduction section of `introduction.mdx` for improved clarity.
- Updated the `quickstart.mdx` to provide a more comprehensive and user-friendly guide, including detailed steps for both code and no-code approaches to creating AI agents.
- Enhanced the `knowledge.mdx` file by renaming the vector store from "Chroma" to "Vector DB" for better clarity in terminology.
- Added prerequisites and tips to the quickstart guide to assist users in setting up their environment effectively.

These changes improve the overall usability and clarity of the documentation, making it easier for users to get started with PraisonAI.
2025-01-16 11:45:01 +00:00
127 changed files with 15731 additions and 893 deletions

No files matched your search

+424 -439
View File
@@ -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 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.chat("Write a movie script about a robot in Mars")
```
Run:
@@ -135,6 +79,381 @@ 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
```
## 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 +466,14 @@ 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
```yaml
framework: crewai
framework: praisonai
topic: Artificial Intelligence
roles:
screenwriter:
@@ -420,62 +486,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,6 +529,17 @@ 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
[![Star History Chart](https://api.star-history.com/svg?repos=MervinPraison/PraisonAI&type=Date)](https://docs.praison.ai)
@@ -525,58 +565,3 @@ Praison AI is an open-sourced software licensed under the **[MIT license](https:
| Realtime Voice Interface | [![Realtime](https://img.youtube.com/vi/frRHfevTCSw/0.jpg)](https://www.youtube.com/watch?v=frRHfevTCSw) |
| Call Interface | [![Call](https://img.youtube.com/vi/m1cwrUG2iAk/0.jpg)](https://www.youtube.com/watch?v=m1cwrUG2iAk) |
## 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.
+43
View File
@@ -0,0 +1,43 @@
FROM mcr.microsoft.com/devcontainers/python:3.11
# Prevent apt from showing prompts
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Create a non-root user
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Create the user and group only if they don't exist
RUN if ! getent group $USER_GID > /dev/null 2>&1; then \
groupadd --gid $USER_GID $USERNAME; \
fi && \
if ! getent passwd $USER_UID > /dev/null 2>&1; then \
useradd --uid $USER_UID --gid $USER_GID -m $USERNAME; \
fi && \
apt-get update && \
apt-get install -y sudo && \
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \
chmod 0440 /etc/sudoers.d/$USERNAME
# Set Python environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# Install Python dependencies
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp
# Switch to non-root user
USER $USERNAME
# Set the default shell to bash
ENV SHELL=/bin/bash
+36
View File
@@ -0,0 +1,36 @@
{
"name": "PraisonAI Development",
"dockerFile": "Dockerfile",
"context": "..",
"runArgs": [
"--env-file",
".env",
"--network=host"
],
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-toolsai.jupyter",
"yzhang.markdown-all-in-one",
"streetsidesoftware.code-spell-checker"
],
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"editor.rulers": [88],
"files.trimTrailingWhitespace": true
}
}
},
"remoteUser": "vscode",
"updateRemoteUserUID": false,
"forwardPorts": [],
"appPort": ["56040:56040"],
"overrideCommand": false,
"init": true
}
+45
View File
@@ -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)
+18
View File
@@ -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())
+10
View File
@@ -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?")
+127
View File
@@ -0,0 +1,127 @@
import asyncio
import logging
from typing import List, Dict, Any
from pydantic import BaseModel
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from tavily import AsyncTavilyClient
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
llm_config = {
"model": "gemini/gemini-1.5-flash-8b",
"response_format": {
"type": "text"
}
}
# Define output model
class SearchResult(BaseModel):
query: str
results: List[Dict[str, Any]]
total_results: int
# Define Tavily search tool
async def tavily_search(query) -> Dict[str, Any]:
"""Async Tavily search tool that returns structured results"""
client = AsyncTavilyClient()
try:
results = await client.search(query)
print(f"Tavily search results: {results}")
return {
"query": query,
"results": results.get("results", []),
"total_results": len(results.get("results", []))
}
except Exception as e:
logging.error(f"Tavily search error: {e}")
return {
"query": query,
"results": [],
"total_results": 0
}
# Define async callback
async def async_callback(output: TaskOutput):
if output.output_format == "JSON":
logging.info(f"Search completed: {output.json_dict.get('query', '')}")
elif output.output_format == "Pydantic":
logging.info(f"Search completed: {output.pydantic}")
async def run_parallel_searches():
# Create search agent with direct tool function
search_agent = Agent(
name="TavilySearchAgent",
role="Search Specialist",
goal="Perform parallel web searches with high accuracy",
backstory="Expert in web search and information retrieval",
tools=[tavily_search],
llm=llm_config
)
# Create summary agent
summary_agent = Agent(
name="ContentSynthesizer",
role="Research Analyst",
goal="Synthesize search results into coherent insights",
backstory="Expert in analyzing and combining multiple sources of information",
llm=llm_config
)
# Define search topics
search_topics = [
"Latest AI breakthroughs 2024",
"Future of quantum computing",
"Advancements in robotics"
]
# Create parallel search tasks
search_tasks = [
Task(
name=f"search_{i}",
description=f"Search and analyze: {topic}",
expected_output="Comprehensive search results with analysis",
agent=search_agent,
async_execution=True,
callback=async_callback,
) for i, topic in enumerate(search_topics)
]
# Create summary task
summary_task = Task(
name="synthesize_results",
description="Create a comprehensive summary of all search findings",
expected_output="Synthesized insights from all searches",
agent=summary_agent,
async_execution=False,
context=search_tasks
)
# Initialize agents manager
agents = PraisonAIAgents(
agents=[search_agent, summary_agent],
tasks=search_tasks + [summary_task]
)
# Execute tasks
results = await agents.astart()
return {
"search_results": [str(results["task_results"][i]) for i in range(len(search_tasks))],
"summary": str(results["task_results"][summary_task.id]),
"topics": search_topics
}
async def main():
try:
logging.info("Starting parallel Tavily searches...")
results = await run_parallel_searches()
logging.info("Search process completed successfully")
print("\nResults Summary:")
for topic, result in zip(results["topics"], results["search_results"]):
print(f"\n{topic}:\n{result}")
print(f"\nFinal Summary:\n{results['summary']}")
except Exception as e:
logging.error(f"Error in execution: {e}")
if __name__ == "__main__":
asyncio.run(main())
+119
View File
@@ -0,0 +1,119 @@
import asyncio
import logging
from typing import List, Dict, Any
from pydantic import BaseModel
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from tavily import AsyncTavilyClient
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Define output model
class SearchResult(BaseModel):
query: str
results: List[Dict[str, Any]]
total_results: int
# Define Tavily search tool
async def tavily_search(query: str) -> Dict[str, Any]:
"""Async Tavily search tool that returns structured results"""
client = AsyncTavilyClient()
try:
results = await client.search(query)
print(f"Tavily search results: {results}")
return {
"query": query,
"results": results.get("results", []),
"total_results": len(results.get("results", []))
}
except Exception as e:
logging.error(f"Tavily search error: {e}")
return {
"query": query,
"results": [],
"total_results": 0
}
# Define async callback
async def async_callback(output: TaskOutput):
if output.output_format == "JSON":
logging.info(f"Search completed: {output.json_dict.get('query', '')}")
elif output.output_format == "Pydantic":
logging.info(f"Search completed: {output.pydantic}")
async def run_parallel_searches():
# Create search agent with direct tool function
search_agent = Agent(
name="TavilySearchAgent",
role="Search Specialist",
goal="Perform parallel web searches with high accuracy",
backstory="Expert in web search and information retrieval",
tools=[tavily_search]
)
# Create summary agent
summary_agent = Agent(
name="ContentSynthesizer",
role="Research Analyst",
goal="Synthesize search results into coherent insights",
backstory="Expert in analyzing and combining multiple sources of information"
)
# Define search topics
search_topics = [
"Latest AI breakthroughs 2024",
"Future of quantum computing",
"Advancements in robotics"
]
# Create parallel search tasks
search_tasks = [
Task(
name=f"search_{i}",
description=f"Search and analyze: {topic}",
expected_output="Comprehensive search results with analysis",
agent=search_agent,
async_execution=True,
callback=async_callback,
output_json=SearchResult
) for i, topic in enumerate(search_topics)
]
# Create summary task
summary_task = Task(
name="synthesize_results",
description="Create a comprehensive summary of all search findings",
expected_output="Synthesized insights from all searches",
agent=summary_agent,
async_execution=False,
context=search_tasks
)
# Initialize agents manager
agents = PraisonAIAgents(
agents=[search_agent, summary_agent],
tasks=search_tasks + [summary_task]
)
# Execute tasks
results = await agents.astart()
return {
"search_results": [str(results["task_results"][i]) for i in range(len(search_tasks))],
"summary": str(results["task_results"][summary_task.id]),
"topics": search_topics
}
async def main():
try:
logging.info("Starting parallel Tavily searches...")
results = await run_parallel_searches()
logging.info("Search process completed successfully")
print("\nResults Summary:")
for topic, result in zip(results["topics"], results["search_results"]):
print(f"\n{topic}:\n{result}")
print(f"\nFinal Summary:\n{results['summary']}")
except Exception as e:
logging.error(f"Error in execution: {e}")
if __name__ == "__main__":
asyncio.run(main())
+24 -3
View File
@@ -12,6 +12,14 @@ from praisonaiagents.main import (
)
from duckduckgo_search import DDGS
from pydantic import BaseModel
import logging
# Configure logging with more detail
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(name)s:%(lineno)d - %(message)s'
)
logger = logging.getLogger(__name__)
console = Console()
@@ -48,7 +56,7 @@ def sync_search_tool(query: str) -> List[Dict]:
error_logs.append(error_msg)
return []
async def async_search_tool(query: str) -> List[Dict]:
async def async_search_tool(query: str) -> Dict:
"""
Asynchronous search using DuckDuckGo.
Args:
@@ -56,23 +64,36 @@ async def async_search_tool(query: str) -> List[Dict]:
Returns:
list: Search results
"""
logger.debug(f"Starting async_search_tool with query: {query}")
display_tool_call(f"Running async search for: {query}", console)
await asyncio.sleep(1) # Simulate network delay
try:
results = []
ddgs = DDGS()
logger.debug("Performing DuckDuckGo search")
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
return results
logger.debug(f"Search completed, found {len(results)} results")
return {
"query": query,
"results": results,
"total_results": len(results)
}
except Exception as e:
error_msg = f"Error during async search: {e}"
logger.error(f"Error in async_search_tool: {e}", exc_info=True)
display_error(error_msg, console)
error_logs.append(error_msg)
return []
return {
"query": query,
"results": [],
"total_results": 0
}
# 3. Define both sync and async callbacks
def sync_callback(output: TaskOutput):
+7
View File
@@ -4,6 +4,13 @@ from typing import List, Dict
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from duckduckgo_search import DDGS
from pydantic import BaseModel
import logging
# Configure logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# 1. Define output model for structured results
class SearchResult(BaseModel):
+8
View File
@@ -0,0 +1,8 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-4o-mini"
)
agent.start("Why sky is Blue?")
+97
View File
@@ -0,0 +1,97 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
from gitingest import ingest
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
return agents.start(context_text)
if __name__ == "__main__":
# Example usage
code_source = "https://github.com/openai/openai-python/tree/main/src/openai/cli/_api/chat" # GitHub URL or local directory
result = analyze_code(code_source)
print(result)
+217
View File
@@ -0,0 +1,217 @@
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict, Any
from gitingest import ingest
# Import the same classes and code from code-analysis-agents.py
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Create code analyzer agent
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
# Create analysis task
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
result = agents.start(context_text)
# Extract the Pydantic model from the result
if isinstance(result, dict) and 'task_results' in result:
# Get the first task result's pydantic output
analysis_result = result['task_results'][0].pydantic
if isinstance(analysis_result, CodeAnalysisReport):
return analysis_result
# If we can't get the Pydantic model, create one from the raw data
return CodeAnalysisReport(**result)
def display_code_metrics(metrics, cols):
"""Display code metrics in columns with color-coded scores"""
for i, metric in enumerate(metrics):
score = metric.score
color = "red" if score < 60 else "orange" if score < 75 else "green"
# Use modulo to alternate between columns
with cols[i % len(cols)]:
st.markdown(f"### {metric.category}")
st.markdown(f"**Score:** :{color}[{score}%]")
for finding in metric.findings:
st.markdown(f"• {finding}")
def display_section(title: str, items: list, icon: str = "•"):
"""Display a section with items in a consistent format"""
st.markdown(f"### {title}")
for item in items:
if isinstance(item, dict):
for key, value in item.items():
st.markdown(f"{icon} **{key}**: {value}")
else:
st.markdown(f"{icon} {item}")
def main():
st.set_page_config(
page_title="Code Analysis Agent",
layout="wide",
initial_sidebar_state="expanded"
)
st.title("Code Analysis Agent")
with st.sidebar:
st.header("Input")
code_source = st.text_input(
"GitHub URL or Local Path",
placeholder="https://github.com/username/repo or /path/to/directory"
)
analyze_button = st.button("Analyze Code", type="primary")
if analyze_button and code_source:
try:
with st.spinner("Analyzing code..."):
result = analyze_code(code_source)
# Overall Metrics
st.header("Overall Metrics")
cols = st.columns(6)
metrics = {
"Overall Quality": result.overall_quality,
"Architecture": result.architecture_score,
"Maintainability": result.maintainability_score,
"Performance": result.performance_score,
"Security": result.security_score,
"Test Coverage": result.test_coverage
}
for (metric, value), col in zip(metrics.items(), cols):
color = "red" if value < 60 else "orange" if value < 75 else "green"
col.metric(metric, f"{value}%")
col.markdown(f":{color}[{'●' * (value // 20)}]")
# Detailed Analysis
st.header("Detailed Analysis")
metric_cols = st.columns(2)
display_code_metrics(result.code_metrics, metric_cols)
# Technology Stack
col1, col2 = st.columns(2)
with col1:
st.header("Technology Stack")
for tech in result.tech_stack:
st.markdown(f"🔧 {tech}")
with col2:
st.header("Complexity Metrics")
for metric, value in result.complexity_metrics.items():
st.metric(metric.replace('_', ' ').title(), value)
# Key Findings
st.header("Key Findings")
cols = st.columns(2)
with cols[0]:
display_section("✅ Strengths", result.key_strengths)
display_section("🔄 Best Practices", result.best_practices)
with cols[1]:
display_section("⚠️ Areas for Improvement", result.improvement_areas)
display_section("❗ Potential Risks", result.potential_risks)
# Recommendations
st.header("Recommendations")
for i, rec in enumerate(result.recommendations, 1):
st.markdown(f"**{i}.** {rec}")
# Documentation Quality
st.header("Documentation")
doc_score = result.documentation_quality
color = "red" if doc_score < 60 else "orange" if doc_score < 75 else "green"
st.markdown(f"Documentation Quality: :{color}[{doc_score}%]")
except Exception as e:
st.error(f"Error analyzing code: {str(e)}")
st.exception(e)
elif analyze_button:
st.warning("Please enter a GitHub URL or local path")
if __name__ == "__main__":
main()
+98
View File
@@ -0,0 +1,98 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
class SkillMetrics(BaseModel):
name: str
score: int
comments: str
class CVAnalysisReport(BaseModel):
overall_score: int
skill_metrics: List[SkillMetrics]
experience_score: int
education_score: int
presentation_score: int
achievement_impact_score: int
market_readiness: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[Dict[str, int]]
soft_skills: List[Dict[str, int]]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
# Create single CV analysis agent
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
# Single comprehensive analysis task
cv_analysis_task = Task(
description="""Perform a detailed CV analysis with scoring metrics and provide output in the following format:
1. Overall Score (0-100):
- Calculate based on weighted average of all metrics
2. Individual Skill Metrics:
- For each major skill found in CV:
* Name of skill
* Score (0-100)
* Specific feedback/comments
3. Core Metrics (0-100 each):
- Experience Score: Based on relevance and years
- Education Score: Based on relevance and level
- Presentation Score: CV format, clarity, structure
- Achievement Impact Score: Measurable results
- Market Readiness: Current market fit
4. Technical Skills:
- List each skill with proficiency score (0-100)
- Example: {"Python": 85, "AWS": 70}
5. Soft Skills:
- List each skill with proficiency score (0-100)
- Example: {"Communication": 90, "Leadership": 75}
6. Detailed Analysis:
- Key Strengths: Top 3-5 standout points
- Areas for Improvement: 3-5 specific points
- Market Fit: Current industry alignment
- Skill Gaps: Missing critical skills for target role
- Key Achievements: Quantifiable accomplishments
- Impact Metrics: {"metric": "value"}
- Areas of Expertise: Primary domains of expertise
7. Recommendations:
- 3-5 actionable steps for improvement
Provide clear justification for all scores and ensure feedback is specific and actionable.""",
expected_output="Structured CV analysis report with detailed metrics and scoring justification",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport
)
# Create and run the agent
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_analysis_task]
)
# Read and pass CV content through start()
with open('cv.txt', 'r') as file:
cv_content = file.read()
# Start the analysis by passing CV content
result = agents.start(cv_content)
print(result)
+202
View File
@@ -0,0 +1,202 @@
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import json
import asyncio
import nest_asyncio
from functools import partial
# Enable nested event loops
nest_asyncio.apply()
class SkillMetrics(BaseModel):
name: str
score: int
comments: str
class CVAnalysisReport(BaseModel):
overall_score: int
skill_metrics: List[SkillMetrics]
experience_score: int
education_score: int
presentation_score: int
achievement_impact_score: int
market_readiness: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[Dict[str, int]]
soft_skills: List[Dict[str, int]]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
async def analyze_cv_async(cv_content):
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
cv_analysis_task = Task(
description="""Perform a detailed CV analysis with scoring metrics and provide output in the following format:
1. Overall Score (0-100):
- Calculate based on weighted average of all metrics
2. Individual Skill Metrics:
- For each major skill found in CV:
* Name of skill
* Score (0-100)
* Specific feedback/comments
3. Core Metrics (0-100 each):
- Experience Score: Based on relevance and years
- Education Score: Based on relevance and level
- Presentation Score: CV format, clarity, structure
- Achievement Impact Score: Measurable results
- Market Readiness: Current market fit
4. Technical Skills:
- List each skill with proficiency score (0-100)
5. Soft Skills:
- List each skill with proficiency score (0-100)
6. Detailed Analysis sections
7. Recommendations:
- 3-5 actionable steps for improvement""",
expected_output="Structured CV analysis report with detailed metrics and scoring justification",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport
)
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_analysis_task]
)
try:
result = await agents.astart(cv_content)
return result['task_results'][0].pydantic
except Exception as e:
print(f"Error during analysis: {str(e)}")
raise e
def analyze_cv(cv_content):
async def run_analysis():
return await analyze_cv_async(cv_content)
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(run_analysis())
return result
except Exception as e:
raise e
finally:
loop.close()
def main():
st.set_page_config(page_title="CV Analyzer", layout="wide")
st.title("Professional CV Analyzer")
# File upload
cv_file = st.file_uploader("Upload your CV (TXT format)", type=['txt'])
if cv_file:
cv_content = cv_file.read().decode()
with st.spinner('Analyzing your CV...'):
try:
analysis = analyze_cv(cv_content)
# Display Overall Score
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Overall Score", f"{analysis.overall_score}/100")
with col2:
st.metric("Market Readiness", f"{analysis.market_readiness}/100")
with col3:
st.metric("Experience Score", f"{analysis.experience_score}/100")
# Core Metrics
st.subheader("Core Metrics")
metrics_cols = st.columns(4)
with metrics_cols[0]:
st.metric("Education", f"{analysis.education_score}/100")
with metrics_cols[1]:
st.metric("Presentation", f"{analysis.presentation_score}/100")
with metrics_cols[2]:
st.metric("Achievement Impact", f"{analysis.achievement_impact_score}/100")
with metrics_cols[3]:
st.metric("Market Readiness", f"{analysis.market_readiness}/100")
# Skill Metrics
st.subheader("Detailed Skill Analysis")
for skill in analysis.skill_metrics:
with st.expander(f"{skill.name} - Score: {skill.score}/100"):
st.write(skill.comments)
# Technical and Soft Skills
col1, col2 = st.columns(2)
with col1:
st.subheader("Technical Skills")
for skill in analysis.technical_skills:
for skill_name, score in skill.items():
st.progress(score/100)
st.caption(f"{skill_name}: {score}/100")
with col2:
st.subheader("Soft Skills")
for skill in analysis.soft_skills:
for skill_name, score in skill.items():
st.progress(score/100)
st.caption(f"{skill_name}: {score}/100")
# Key Information
st.subheader("Key Analysis")
col1, col2 = st.columns(2)
with col1:
st.write("🎯 Key Strengths")
for strength in analysis.key_strengths:
st.write(f"• {strength}")
st.write("🎮 Areas of Expertise")
for expertise in analysis.areas_of_expertise:
st.write(f"• {expertise}")
with col2:
st.write("🔄 Areas for Improvement")
for area in analysis.areas_for_improvement:
st.write(f"• {area}")
st.write("⚠️ Skill Gaps")
for gap in analysis.skill_gaps:
st.write(f"• {gap}")
# Impact Metrics
st.subheader("Impact Metrics")
for metric in analysis.impact_metrics:
for key, value in metric.items():
st.metric(key, value)
# Recommendations
st.subheader("📋 Recommendations")
for rec in analysis.recommendations:
st.write(f"• {rec}")
except Exception as e:
st.error(f"An error occurred during analysis: {str(e)}")
else:
st.info("Please upload your CV in TXT format to begin the analysis")
if __name__ == "__main__":
main()
+61
View File
@@ -0,0 +1,61 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
class CVAnalysisReport(BaseModel):
overall_score: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[str]
soft_skills: List[str]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
# Create single CV analysis agent
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
# Read CV content first
with open('cv.txt', 'r') as file:
cv_content = file.read()
cv_key_strengths = Task(
description="List the key strengths to look",
expected_output="List of key strengths",
agent=cv_analyzer,
)
# Single comprehensive analysis task with CV content in context
cv_analysis_task = Task(
description="""Analyze the CV comprehensively including:
1. Technical and soft skills assessment
2. Experience and achievements evaluation
3. Overall CV evaluation with recommendations
Provide detailed insights and actionable recommendations.""",
expected_output="Complete CV analysis report",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport,
context=[cv_content, cv_key_strengths] # Pass CV content directly in task context
)
# Create and run the agent
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_key_strengths,cv_analysis_task],
process="sequential"
)
# Start the analysis - no need to pass content again since it's in task context
result = agents.start()
print(result)
+27
View File
@@ -0,0 +1,27 @@
# example tools.py
from duckduckgo_search import DDGS
from praisonai_tools import BaseTool
class InternetSearchTool(BaseTool):
name: str = "InternetSearchTool"
description: str = "Search Internet for relevant information based on a query or latest news"
def _run(self, query: str):
ddgs = DDGS()
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
return results
# Example agent
from praisonaiagents import Agent
from praisonaiagents import PraisonAIAgents
agent = Agent(
name="Internet Search Agent",
tools=[InternetSearchTool],
instructions="""
You are an agent that can search the internet for relevant information based on a query or latest news.
"""
)
# Run the agent
result = PraisonAIAgents(agents=[agent], verbose=10).start()
print(result)
+57
View File
@@ -0,0 +1,57 @@
Name: Alex Johnson
Location: London, UK
Professional Summary
Dynamic and results-oriented leader with a proven track record of driving innovation, scaling operations, and achieving transformational growth. Over 15 years of experience in engineering, strategic management, and executive leadership in the automotive and renewable energy sectors. Passionate about sustainable technologies and visionary leadership.
Professional Experience
Chief Operating Officer (COO)
NextGen Mobility Ltd. | Palo Alto, CA | 2020 – Present
Spearheaded global operations for an electric vehicle company, scaling production by 200% in three years.
Introduced automation-driven supply chain strategies, reducing costs by 15%.
Collaborated with R&D to launch three new EV models, driving 25% revenue growth annually.
Vice President of Engineering
ElectroDrive Systems | San Francisco, CA | 2015 – 2020
Led a team of 500+ engineers in developing next-generation EV batteries, achieving a 30% increase in energy efficiency.
Secured $50M in government funding for sustainable energy innovation.
Drove cross-functional collaboration, aligning product development with market needs.
Director of Renewable Energy Initiatives
GreenTech Innovations | London, UK | 2011 – 2015
Oversaw £100M projects in solar and wind energy deployment across Europe.
Established partnerships with policymakers to influence renewable energy legislation.
Pioneered a smart energy grid system, enhancing energy distribution efficiency by 40%.
Senior Project Manager
Innovate Auto Ltd. | Munich, Germany | 2008 – 2011
Managed R&D projects for autonomous driving technologies.
Delivered projects 20% under budget through strategic resource allocation.
Filed 10+ patents in automotive AI and renewable integration.
Mechanical Engineer
AutoFusion Technologies | Berlin, Germany | 2005 – 2008
Designed core systems for EV powertrains, optimising energy consumption by 15%.
Collaborated with suppliers to improve material efficiency, cutting costs by £5M annually.
Education
MBA in Strategic Management
Harvard Business School | Cambridge, MA | 2015
MSc in Renewable Energy Engineering
Imperial College London | London, UK | 2007
BSc in Mechanical Engineering
Technical University of Munich | Munich, Germany | 2005
Skills
Strategic Leadership & Visionary Thinking
Electric Vehicle Engineering
Renewable Energy Systems
Global Operations Management
Policy Advocacy & Government Relations
Supply Chain Optimisation
Achievements
Featured in Forbes 30 Under 40 for innovations in EV technology.
Author of The Future of Sustainable Mobility.
Keynote speaker at World Energy Summit, 2023.
+9
View File
@@ -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?")
+62
View File
@@ -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})
+54
View File
@@ -0,0 +1,54 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
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",
},
},
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="deepseek-r1"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
+62
View File
@@ -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})
+39
View File
@@ -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
+159
View File
@@ -0,0 +1,159 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
+159
View File
@@ -0,0 +1,159 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
+210
View File
@@ -0,0 +1,210 @@
import streamlit as st
import os
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import tempfile
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Set page config
st.set_page_config(
page_title="Hackathon Project Evaluator",
page_icon="🏆",
layout="wide"
)
# Create Vision Analysis Agent
@st.cache_resource
def get_hackathon_judge():
return Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
hackathon_judge = get_hackathon_judge()
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
elif isinstance(response, str):
evaluation_data = json.loads(response)
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
# Title and description
st.title("🏆 Hackathon Judge Agent")
st.markdown("""
Upload your hackathon project demonstration video for an AI-powered evaluation.
Get comprehensive feedback on various aspects of your project.
""")
# File uploader
uploaded_file = st.file_uploader("Choose a video file", type=['mp4', 'avi', 'mov', 'mkv'])
if uploaded_file:
# Create a temporary file to store the video
with tempfile.NamedTemporaryFile(delete=False, suffix='.'+uploaded_file.name.split('.')[-1]) as tmp_file:
tmp_file.write(uploaded_file.getvalue())
video_path = tmp_file.name
with st.spinner("🤖 AI is evaluating your project..."):
try:
# Evaluate the project
result = evaluate_project(video_path)
# Display results
st.header("Overall Score")
st.metric("Overall Score", f"{result.overall_score}/100")
# Display detailed scores
st.header("Detailed Scores")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Innovation", f"{result.innovation_score}/100")
st.metric("Technical Complexity", f"{result.technical_complexity}/100")
with col2:
st.metric("Presentation", f"{result.presentation_quality}/100")
st.metric("User Experience", f"{result.user_experience}/100")
with col3:
st.metric("Completeness", f"{result.completeness}/100")
# Display qualitative feedback
st.header("Key Strengths")
for strength in result.key_strengths:
st.write(f"• {strength}")
st.header("Areas for Improvement")
for area in result.areas_for_improvement:
st.write(f"• {area}")
st.header("Technical Highlights")
for highlight in result.technical_highlights:
st.write(f"• {highlight}")
st.header("Notable Features")
for feature in result.notable_features:
st.write(f"• {feature}")
st.header("Recommendations")
for rec in result.recommendations:
st.write(f"• {rec}")
# Market Analysis
st.header("Market Analysis")
col1, col2 = st.columns(2)
with col1:
st.subheader("Market Potential")
st.write(result.market_potential)
with col2:
st.subheader("Scalability Assessment")
st.write(result.scalability_assessment)
except Exception as e:
st.error(f"Error evaluating the project: {str(e)}")
finally:
# Clean up the temporary file
os.unlink(video_path)
else:
# Display placeholder content
st.info("👆 Upload a video file to get started!")
File renamed without changes.
+28 -6
View File
@@ -1,6 +1,7 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import logging
import os
import json
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@@ -8,11 +9,29 @@ logger = logging.getLogger(__name__)
# Define the configuration for the Knowledge instance
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "knowledge_test",
"path": ".praison",
"collection_name": "praison",
"path": os.path.abspath("./.praison"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
@@ -23,17 +42,20 @@ knowledge_agent = Agent(
role="Information Specialist",
goal="Store and retrieve knowledge efficiently",
backstory="Expert in managing and utilizing stored knowledge",
knowledge=["sample.pdf"],
knowledge_config=config,
verbose=True
)
# Define a task for the agent
knowledge_task = Task(
name="knowledge_task",
description="Who is Mervin Praison?",
description="KAG",
expected_output="Answer to the question",
agent=knowledge_agent
agent=knowledge_agent,
context=[
{
"embedding_db_config": json.dumps(config["vector_store"])
}
]
)
# Create and start the agents
+3 -2
View File
@@ -4,7 +4,7 @@ config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "custom_knowledge",
"collection_name": "praison",
"path": ".praison",
}
}
@@ -14,7 +14,8 @@ agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["large.pdf"],
knowledge_config=config
knowledge_config=config,
user_id="user1"
)
agent.start("What is KAG in one line?")
+44
View File
@@ -0,0 +1,44 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
knowledge = Knowledge(config)
# Search for memories based on a query
query = "KAG"
logger.info(f"Searching for memories with query: {query}")
search_results = knowledge.search(query, user_id="user1")
logger.info(f"Search results: {search_results}")
print(f"\nSearch results for '{query}':")
print(search_results)
+220
View File
@@ -0,0 +1,220 @@
from mem0 import Memory
import logging
import json
import os
import time
from datetime import datetime
from typing import Dict, Any, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MemoryManager:
def __init__(self):
"""Initialize Mem0 Memory manager with configuration"""
# Define the complete configuration with only supported fields
config = {
"version": "v1.1",
"custom_prompt": None,
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Ensure storage directory exists
storage_path = os.path.abspath("./.praison/storage")
if os.path.exists(storage_path):
logger.info(f"Clearing existing storage at {storage_path}")
import shutil
shutil.rmtree(storage_path)
os.makedirs(storage_path, exist_ok=True)
logger.info(f"Created storage path: {storage_path}")
# Initialize memory
self.memory = Memory.from_config(config)
logger.info("Memory manager initialized")
def pretty_print(self, data: Any) -> None:
"""Helper function to print memory data in a readable format"""
if isinstance(data, (dict, list)):
print(json.dumps(data, indent=2))
else:
print(data)
def extract_memory_id(self, result: Any) -> Optional[str]:
"""Extract memory ID from the result, handling different formats"""
try:
if isinstance(result, dict):
# v1.1 format
memories = result.get('results', [])
return memories[0]['id'] if memories else None
elif isinstance(result, list):
# v1.0 format
return result[0]['id'] if result else None
return None
except (KeyError, IndexError) as e:
logger.warning(f"Could not extract memory ID from result: {e}")
return None
def prepare_metadata(self, metadata: Optional[Dict]) -> Dict:
"""Prepare metadata by converting values to acceptable types"""
if not metadata:
return {}
clean_metadata = {}
for key, value in metadata.items():
if isinstance(value, (str, int, float, bool)):
clean_metadata[key] = value
elif isinstance(value, list):
clean_metadata[key] = ','.join(map(str, value))
elif isinstance(value, dict):
clean_metadata[key] = json.dumps(value)
else:
clean_metadata[key] = str(value)
return clean_metadata
def verify_memory_addition(self, user_id: str, max_retries: int = 3) -> bool:
"""Verify that memory was added successfully"""
for attempt in range(max_retries):
try:
time.sleep(0.5) # Brief pause to allow indexing
memories = self.memory.get_all(user_id=user_id)
if len(memories.get('results', [])) > 0:
return True
logger.warning(f"Memory not found on attempt {attempt + 1}")
except Exception as e:
logger.warning(f"Verification attempt {attempt + 1} failed: {e}")
if attempt < max_retries - 1:
time.sleep(1)
return False
def add_memory(self, text: str, user_id: Optional[str] = None, metadata: Optional[Dict] = None) -> Dict:
"""Add a new memory with error handling and verification"""
try:
logger.info(f"Adding memory for user {user_id}")
clean_metadata = self.prepare_metadata(metadata)
logger.debug(f"Prepared metadata: {clean_metadata}")
messages = [{"role": "user", "content": text}]
result = self.memory.add(
messages=messages,
user_id=user_id,
metadata=clean_metadata
)
if self.verify_memory_addition(user_id):
logger.info("Memory added and verified successfully")
else:
logger.warning("Memory addition could not be verified")
return result
except Exception as e:
logger.error(f"Failed to add memory: {str(e)}")
raise
def get_all_memories(self, user_id: Optional[str] = None) -> Dict:
"""Retrieve all memories for a user"""
try:
logger.info(f"Retrieving all memories for user {user_id}")
memories = self.memory.get_all(user_id=user_id)
count = len(memories.get('results', []))
logger.info(f"Retrieved {count} memories")
return memories
except Exception as e:
logger.error(f"Failed to retrieve memories: {str(e)}")
raise
def search_memories(self, query: str, user_id: Optional[str] = None, limit: int = 5) -> Dict:
"""Search memories with a query"""
try:
logger.info(f"Searching memories with query: {query}")
results = self.memory.search(
query=query,
user_id=user_id,
limit=limit
)
count = len(results.get('results', []))
logger.info(f"Found {count} matching memories")
return results
except Exception as e:
logger.error(f"Search failed: {str(e)}")
raise
def main():
try:
# Initialize memory manager
manager = MemoryManager()
# Add a test memory
print("\n1. Adding a new memory:")
metadata = {
"category": "hobbies",
"timestamp": datetime.now().isoformat(),
"tags": "tennis,learning",
"priority": 1,
"source": "user_input"
}
result = manager.add_memory(
text="I am working on improving my tennis skills. Suggest some online courses.",
user_id="alice",
metadata=metadata
)
manager.pretty_print(result)
# Wait briefly for indexing
time.sleep(1)
print("\n2. Retrieving all memories:")
all_memories = manager.get_all_memories(user_id="alice")
manager.pretty_print(all_memories)
print("\n3. Searching memories:")
search_results = manager.search_memories(
query="What are Alice's hobbies?",
user_id="alice",
limit=5
)
manager.pretty_print(search_results)
# Print summary
print("\nMemory Store Summary:")
total_memories = len(all_memories.get('results', []))
print(f"Total memories stored: {total_memories}")
if total_memories > 0:
print("Available memories:")
for mem in all_memories['results']:
print(f"- {mem.get('memory', 'No content')}")
except Exception as e:
logger.error(f"Main process failed: {str(e)}", exc_info=True)
raise
if __name__ == "__main__":
main()
+143
View File
@@ -0,0 +1,143 @@
from mem0 import Memory
import logging
import json
import os
from typing import Dict, Any, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MemorySearcher:
def __init__(self):
"""Initialize Mem0 Memory searcher with configuration"""
# Define the configuration
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Initialize memory
self.memory = Memory.from_config(config)
logger.info("Memory searcher initialized")
def pretty_print(self, data: Any) -> None:
"""Helper function to print data in a readable format"""
if isinstance(data, (dict, list)):
print(json.dumps(data, indent=2))
else:
print(data)
def get_all_memories(self, user_id: Optional[str] = None) -> Dict:
"""Retrieve all memories for a user"""
try:
logger.info(f"Retrieving all memories for user {user_id}")
memories = self.memory.get_all(user_id=user_id)
count = len(memories.get('results', []))
logger.info(f"Retrieved {count} memories")
return memories
except Exception as e:
logger.error(f"Failed to retrieve memories: {str(e)}")
raise
def search_memories(self, query: str, user_id: Optional[str] = None, limit: int = 5) -> Dict:
"""Search memories with a query"""
try:
logger.info(f"Searching memories with query: {query}")
results = self.memory.search(
query=query,
user_id=user_id,
limit=limit
)
count = len(results.get('results', []))
logger.info(f"Found {count} matching memories")
return results
except Exception as e:
logger.error(f"Search failed: {str(e)}")
raise
def list_unique_users(self) -> list:
"""List all unique users in the memory store"""
try:
all_memories = self.memory.get_all()
users = set()
for memory in all_memories.get('results', []):
if 'user_id' in memory:
users.add(memory['user_id'])
return sorted(list(users))
except Exception as e:
logger.error(f"Failed to list users: {str(e)}")
raise
def main():
try:
# Initialize memory searcher
searcher = MemorySearcher()
# Get list of users
print("\n1. Available users in the memory store:")
users = searcher.list_unique_users()
searcher.pretty_print(users)
if not users:
print("No users found in the memory store. Please add some memories first.")
return
# Example user (using first user found)
example_user = users[0]
print(f"\n2. All memories for user '{example_user}':")
all_memories = searcher.get_all_memories(user_id=example_user)
searcher.pretty_print(all_memories)
print(f"\n3. Searching memories for user '{example_user}':")
search_results = searcher.search_memories(
query="What are their hobbies?",
user_id=example_user,
limit=5
)
searcher.pretty_print(search_results)
# Print summary
print("\nMemory Store Summary:")
total_memories = len(all_memories.get('results', []))
print(f"Total memories for {example_user}: {total_memories}")
if total_memories > 0:
print("Available memories:")
for mem in all_memories['results']:
print(f"- {mem.get('memory', 'No content')}")
if 'metadata' in mem:
print(f" Metadata: {mem['metadata']}")
except Exception as e:
logger.error(f"Main process failed: {str(e)}", exc_info=True)
raise
if __name__ == "__main__":
main()
+26
View File
@@ -0,0 +1,26 @@
from mem0 import Memory
import os
import json
# Basic configuration
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison",
}
}
}
# Initialize memory
memory = Memory.from_config(config)
# Search Alice's hobbies
search_results = memory.search(
query="KAG",
user_id="user1",
limit=5
)
print(search_results)
+46
View File
@@ -0,0 +1,46 @@
from mem0 import Memory
import os
import json
# Basic configuration
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage")
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini"
}
}
}
# Initialize memory
memory = Memory.from_config(config)
# Search Alice's hobbies
search_results = memory.search(
query="What are Alice's hobbies?",
user_id="alice",
limit=5
)
# Print results in a readable format
print("\nAlice's Memories:")
for memory in search_results['results']:
print(f"\nMemory: {memory['memory']}")
print(f"Score: {memory['score']}")
if 'metadata' in memory:
print("Metadata:")
print(json.dumps(memory['metadata'], indent=2))
-2
View File
@@ -9,7 +9,6 @@ from .tools.tools import Tools
from .agents.autoagents import AutoAgents
from .knowledge.knowledge import Knowledge
from .knowledge.chunking import Chunking
from .memory.memory import Memory
from .main import (
TaskOutput,
ReflectionOutput,
@@ -38,7 +37,6 @@ __all__ = [
'TaskOutput',
'ReflectionOutput',
'AutoAgents',
'Memory',
'display_interaction',
'display_self_reflection',
'display_instruction',
+445 -252
View File
@@ -71,10 +71,15 @@ class Agent:
import inspect
# Langchain tools
if inspect.isclass(func) and hasattr(func, 'run'):
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}")
@@ -187,10 +192,26 @@ class Agent:
reflect_llm: Optional[str] = None,
user_id: Optional[str] = None
):
# Add check at start if memory is requested
if memory is not None:
try:
from ..memory.memory import Memory
MEMORY_AVAILABLE = True
except ImportError:
raise ImportError(
"Memory features requested in Agent but memory dependencies not installed. "
"Please install with: pip install \"praisonaiagents[memory]\""
)
# 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")
# Configure logging to suppress unwanted outputs
logging.getLogger("litellm").setLevel(logging.WARNING)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("httpcore").setLevel(logging.WARNING)
# If instructions are provided, use them to set role, goal, and backstory
if instructions:
self.name = name or "Agent"
@@ -210,7 +231,34 @@ class Agent:
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._using_custom_llm = False
# If the user passes a dictionary (for advanced configuration)
if isinstance(llm, dict) and "model" in llm:
try:
from ..llm.llm import LLM
self.llm_instance = LLM(**llm) # Pass all dict items as kwargs
self._using_custom_llm = True
except ImportError as e:
raise ImportError(
"LLM features requested but dependencies not installed. "
"Please install with: pip install \"praisonaiagents[llm]\""
) from e
# If the user passes a string with a slash (provider/model)
elif isinstance(llm, str) and "/" in llm:
try:
from ..llm.llm import LLM
# Pass the entire string so LiteLLM can parse provider/model
self.llm_instance = LLM(model=llm)
self._using_custom_llm = True
except ImportError as e:
raise ImportError(
"LLM features requested but dependencies not installed. "
"Please install with: pip install \"praisonaiagents[llm]\""
) from e
# Otherwise, fall back to OpenAI environment/name
else:
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
@@ -249,16 +297,20 @@ Your Goal: {self.goal}
self.agent_id = str(uuid.uuid4())
# Store user_id
self.user_id = user_id
self.user_id = user_id or "praison"
# 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)
# 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."""
@@ -313,14 +365,22 @@ Your Goal: {self.goal}
if func:
try:
# If it's a class with run method, instantiate and call run
if inspect.isclass(func) and hasattr(func, 'run'):
# 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()
# Extract only the parameters that run() expects
run_params = {k: v for k, v in arguments.items()
if k in inspect.signature(instance.run).parameters
and k != 'self'}
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)
@@ -466,185 +526,216 @@ Your Goal: {self.goal}
# Append found knowledge to the prompt
prompt = f"{prompt}\n\nKnowledge: {knowledge_content}"
if self.use_system_prompt:
system_prompt = f"""{self.backstory}\n
if self._using_custom_llm:
try:
# Pass everything to LLM class
response_text = self.llm_instance.get_response(
prompt=prompt,
system_prompt=f"{self.backstory}\n\nYour Role: {self.role}\n\nYour Goal: {self.goal}" if self.use_system_prompt else None,
chat_history=self.chat_history,
temperature=temperature,
tools=tools,
output_json=output_json,
output_pydantic=output_pydantic,
verbose=self.verbose,
markdown=self.markdown,
self_reflect=self.self_reflect,
max_reflect=self.max_reflect,
min_reflect=self.min_reflect,
console=self.console,
agent_name=self.name,
agent_role=self.role,
agent_tools=[t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools],
execute_tool_fn=self.execute_tool # Pass tool execution function
)
self.chat_history.append({"role": "user", "content": prompt})
self.chat_history.append({"role": "assistant", "content": response_text})
return response_text
except Exception as e:
display_error(f"Error in LLM chat: {e}")
return None
else:
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: {output_json.schema_json()}"
elif output_pydantic:
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_pydantic.schema_json()}"
else:
system_prompt = None
"""
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)
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
# 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})
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()
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"
})
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"), "")
response = self._chat_completion(messages, temperature=temperature)
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()
# 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 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 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
if self.verbose:
display_tool_call(f"Agent {self.name} is calling function '{function_name}' with arguments: {arguments}", console=self.console)
reflection_prompt = f"""
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})
"""
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
)
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
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
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)
# 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
messages.append({"role": "assistant", "content": f"Self Reflection: {reflection_output.reflection} Satisfactory?: {reflection_output.satisfactory}"})
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
# 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 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
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."""
@@ -656,98 +747,153 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
cleaned = cleaned[len("```"):].strip()
if cleaned.endswith("```"):
cleaned = cleaned[:-3].strip()
return cleaned
return cleaned
async def achat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
"""Async version of chat method"""
async def achat(self, prompt: str, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
"""Async version of chat method. TODO: Requires Syncing with chat method."""
try:
# Build system prompt
system_prompt = self.system_prompt
if output_json:
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
elif output_pydantic:
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_pydantic.schema_json()}"
# 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:
if isinstance(search_results, dict) and 'results' in search_results:
knowledge_content = "\n".join([result['memory'] for result in search_results['results']])
else:
knowledge_content = "\n".join(search_results)
prompt = f"{prompt}\n\nKnowledge: {knowledge_content}"
# 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 "")}
]
if self._using_custom_llm:
try:
response_text = await self.llm_instance.get_response_async(
prompt=prompt,
system_prompt=f"{self.backstory}\n\nYour Role: {self.role}\n\nYour Goal: {self.goal}" if self.use_system_prompt else None,
chat_history=self.chat_history,
temperature=temperature,
tools=tools,
output_json=output_json,
output_pydantic=output_pydantic,
verbose=self.verbose,
markdown=self.markdown,
self_reflect=self.self_reflect,
max_reflect=self.max_reflect,
min_reflect=self.min_reflect,
console=self.console,
agent_name=self.name,
agent_role=self.role,
agent_tools=[t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools],
execute_tool_fn=self.execute_tool_async
)
self.chat_history.append({"role": "user", "content": prompt})
self.chat_history.append({"role": "assistant", "content": response_text})
return response_text
except Exception as e:
display_error(f"Error in LLM chat: {e}")
return None
# For OpenAI client
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:
# 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"]:
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 item in prompt:
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
if isinstance(prompt, list):
messages.append({"role": "user", "content": prompt})
else:
response = await async_client.chat.completions.create(
model=self.llm,
messages=messages,
temperature=temperature
)
return response.choices[0].message.content
messages.append({"role": "user", "content": prompt})
reflection_count = 0
start_time = time.time()
while True:
try:
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
except Exception as e:
display_error(f"Error in chat completion: {e}")
display_error(f"Error in achat: {e}")
return None
async def _achat_completion(self, response, tools):
@@ -808,10 +954,57 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
display_error(f"Error in _achat_completion: {e}")
return None
async def astart(self, prompt: str, **kwargs):
"""Async version of start method"""
return await self.achat(prompt, **kwargs)
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)
return self.chat(prompt, **kwargs)
async def execute_tool_async(self, function_name: str, arguments: Dict[str, Any]) -> Any:
"""Async version of execute_tool"""
try:
logging.info(f"Executing async 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):
func = tool
break
if func is None:
logging.error(f"Function {function_name} not found in tools")
return {"error": f"Function {function_name} not found in tools"}
try:
if inspect.iscoroutinefunction(func):
logging.debug(f"Executing async function: {function_name}")
result = await func(**arguments)
else:
logging.debug(f"Executing sync function in executor: {function_name}")
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(None, lambda: func(**arguments))
# Ensure result is JSON serializable
logging.debug(f"Raw result from tool: {result}")
if result is None:
return {"result": None}
try:
json.dumps(result) # Test serialization
return result
except TypeError:
logging.warning(f"Result not JSON serializable, converting to string: {result}")
return {"result": str(result)}
except Exception as e:
logging.error(f"Error executing {function_name}: {str(e)}", exc_info=True)
return {"error": f"Error executing {function_name}: {str(e)}"}
except Exception as e:
logging.error(f"Error in execute_tool_async: {str(e)}", exc_info=True)
return {"error": f"Error in execute_tool_async: {str(e)}"}
+142 -29
View File
@@ -45,12 +45,24 @@ def process_video(video_path: str, seconds_per_frame=2):
return base64_frames
class PraisonAIAgents:
def __init__(self, agents, tasks=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None, memory=False, memory_config=None, embedder=None, user_id=None):
def __init__(self, agents, tasks=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None, memory=False, memory_config=None, embedder=None, user_id=None, max_iter=10):
# Add check at the start if memory is requested
if memory:
try:
from ..memory.memory import Memory
MEMORY_AVAILABLE = True
except ImportError:
raise ImportError(
"Memory features requested but memory dependencies not installed. "
"Please install with: pip install \"praisonaiagents[memory]\""
)
if not agents:
raise ValueError("At least one agent must be provided")
self.run_id = str(uuid.uuid4()) # Auto-generate run_id
self.user_id = user_id # Optional user_id
self.user_id = user_id or "praison" # Optional user_id
self.max_iter = max_iter # Add max_iter parameter
# Pass user_id to each agent
for agent in agents:
@@ -229,15 +241,46 @@ You need to do the following task: {task.description}.
Expected Output: {task.expected_output}.
"""
if task.context:
context_results = ""
for context_task in task.context:
if context_task.result:
context_results += f"Result of previous task {context_task.name if context_task.name else context_task.description}: {context_task.result.raw}\n"
else:
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
context_results = [] # Use list to avoid duplicates
for context_item in task.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
elif isinstance(context_item, dict) and "vector_store" in context_item:
from ..knowledge.knowledge import Knowledge
try:
# Handle both string and dict configs
cfg = context_item["vector_store"]
if isinstance(cfg, str):
cfg = json.loads(cfg)
knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
# Only use user_id as filter
db_results = knowledge.search(
task.description,
user_id=self.user_id if self.user_id else None
)
context_results.append(f"[DB Context]: {str(db_results)}")
except Exception as e:
context_results.append(f"[Vector DB Error]: {e}")
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Here are the results of previous tasks that might be useful:\n
{context_results}
Context:
{' '.join(unique_contexts)}
"""
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
@@ -347,7 +390,15 @@ Here are the results of previous tasks that might be useful:\n
task.status = "completed"
# Run execute_callback for memory operations
try:
await task.execute_callback(task_output)
try:
# If a loop is already running, just create the task
loop = asyncio.get_running_loop()
loop.create_task(task.execute_callback(task_output))
except RuntimeError:
# Otherwise, create and set a new loop, and run the callback
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.create_task(task.execute_callback(task_output))
except Exception as e:
logger.error(f"Error executing memory callback for task {task_id}: {e}")
logger.exception(e)
@@ -356,7 +407,12 @@ Here are the results of previous tasks that might be useful:\n
if task.callback:
try:
if asyncio.iscoroutinefunction(task.callback):
await task.callback(task_output)
if asyncio.get_event_loop().is_running():
asyncio.create_task(task.callback(task_output))
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(task.callback(task_output))
else:
task.callback(task_output)
except Exception as e:
@@ -389,7 +445,8 @@ Here are the results of previous tasks that might be useful:\n
tasks=self.tasks,
agents=self.agents,
manager_llm=self.manager_llm,
verbose=self.verbose
verbose=self.verbose,
max_iter=self.max_iter
)
if self.process == "workflow":
@@ -427,8 +484,16 @@ Here are the results of previous tasks that might be useful:\n
else:
self.run_task(task_id)
async def astart(self):
async def astart(self, content=None, **kwargs):
"""Async version of start method"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
if not task.context:
task.context = []
task.context.append(content)
await self.arun_all_tasks()
return {
"task_status": self.get_all_tasks_status(),
@@ -485,16 +550,48 @@ You need to do the following task: {task.description}.
Expected Output: {task.expected_output}.
"""
if task.context:
context_results = ""
for context_task in task.context:
if context_task.result:
context_results += f"Result of previous task {context_task.name if context_task.name else context_task.description}: {context_task.result.raw}\n"
else:
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
context_results = [] # Use list to avoid duplicates
for context_item in task.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
elif isinstance(context_item, dict) and "vector_store" in context_item:
from ..knowledge.knowledge import Knowledge
try:
# Handle both string and dict configs
cfg = context_item["vector_store"]
if isinstance(cfg, str):
cfg = json.loads(cfg)
knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
# Only use user_id as filter
db_results = knowledge.search(
task.description,
user_id=self.user_id if self.user_id else None
)
context_results.append(f"[DB Context]: {str(db_results)}")
except Exception as e:
context_results.append(f"[Vector DB Error]: {e}")
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Here are the results of previous tasks that might be useful:\n
{context_results}
Context:
{' '.join(unique_contexts)}
"""
# Add memory context if available
if task.memory:
try:
@@ -623,12 +720,15 @@ Here are the results of previous tasks that might be useful:\n
task.status = "completed"
# Run execute_callback for memory operations
try:
if asyncio.get_event_loop().is_running():
asyncio.create_task(task.execute_callback(task_output))
else:
try:
# If a loop is already running, just create the task
loop = asyncio.get_running_loop()
loop.create_task(task.execute_callback(task_output))
except RuntimeError:
# Otherwise, create and set a new loop, and run the callback
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(task.execute_callback(task_output))
loop.create_task(task.execute_callback(task_output))
except Exception as e:
logger.error(f"Error executing memory callback for task {task_id}: {e}")
logger.exception(e)
@@ -675,7 +775,8 @@ Here are the results of previous tasks that might be useful:\n
tasks=self.tasks,
agents=self.agents,
manager_llm=self.manager_llm,
verbose=self.verbose
verbose=self.verbose,
max_iter=self.max_iter
)
if self.process == "workflow":
@@ -714,12 +815,24 @@ Here are the results of previous tasks that might be useful:\n
return str(agent[0])
return None
def start(self):
def start(self, content=None, **kwargs):
"""Start agent execution with optional content and config"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
# If context is empty, initialize it
if not task.context:
task.context = []
# Add content to context
task.context.append(content)
# Run tasks as before
self.run_all_tasks()
return {
"task_status": self.get_all_tasks_status(),
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
}
}
def set_state(self, key: str, value: Any) -> None:
"""Set a state value"""
+29 -11
View File
@@ -84,8 +84,8 @@ class Knowledge:
@cached_property
def config(self):
# Generate unique collection name for each instance
collection_name = f"test_{int(time.time())}_{str(uuid.uuid4())[:8]}"
# Generate unique collection name for each instance (only if not provided in config)
default_collection = f"test_{int(time.time())}_{str(uuid.uuid4())[:8]}"
persist_dir = ".praison"
# Create persistent client config
@@ -93,9 +93,11 @@ class Knowledge:
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": collection_name,
"collection_name": default_collection,
"path": persist_dir,
"client": self._deps['chromadb'].PersistentClient(path=persist_dir)
"client": self._deps['chromadb'].PersistentClient(path=persist_dir),
"host": None,
"port": None
}
},
"version": "v1.1",
@@ -104,13 +106,29 @@ class Knowledge:
# If config is provided, merge it with base config
if self._config:
if "vector_store" in self._config and "config" in self._config["vector_store"]:
config_copy = self._config["vector_store"]["config"].copy()
for key in ["collection_name", "client"]:
if key in config_copy:
del config_copy[key]
base_config["vector_store"]["config"].update(config_copy)
# Merge version if provided
if "version" in self._config:
base_config["version"] = self._config["version"]
# Merge vector_store config
if "vector_store" in self._config:
if "provider" in self._config["vector_store"]:
base_config["vector_store"]["provider"] = self._config["vector_store"]["provider"]
if "config" in self._config["vector_store"]:
config_copy = self._config["vector_store"]["config"].copy()
# Only exclude client as it's managed internally
if "client" in config_copy:
del config_copy["client"]
base_config["vector_store"]["config"].update(config_copy)
# Merge embedder config if provided
if "embedder" in self._config:
base_config["embedder"] = self._config["embedder"]
# Merge llm config if provided
if "llm" in self._config:
base_config["llm"] = self._config["llm"]
return base_config
@cached_property
+20
View File
@@ -0,0 +1,20 @@
import logging
import warnings
# Suppress all relevant logs at module level
logging.getLogger("litellm").setLevel(logging.ERROR)
logging.getLogger("openai").setLevel(logging.ERROR)
logging.getLogger("httpx").setLevel(logging.ERROR)
logging.getLogger("httpcore").setLevel(logging.ERROR)
logging.getLogger("pydantic").setLevel(logging.ERROR)
# Suppress pydantic warnings
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
# Configure logging to suppress all INFO messages
logging.basicConfig(level=logging.WARNING)
# Import after suppressing warnings
from .llm import LLM, LLMContextLengthExceededException
__all__ = ["LLM", "LLMContextLengthExceededException"]
+823
View File
@@ -0,0 +1,823 @@
import logging
import os
import warnings
from typing import Any, Dict, List, Optional, Union, Literal, Callable
from pydantic import BaseModel
import time
import json
from ..main import (
display_error,
display_tool_call,
display_instruction,
display_interaction,
display_generating,
display_self_reflection,
ReflectionOutput,
)
from rich.console import Console
from rich.live import Live
class LLMContextLengthExceededException(Exception):
"""Raised when LLM context length is exceeded"""
def __init__(self, message: str):
self.message = message
super().__init__(self.message)
def _is_context_limit_error(self, error_message: str) -> bool:
"""Check if error is related to context length"""
context_limit_phrases = [
"maximum context length",
"context window is too long",
"context length exceeded",
"context_length_exceeded"
]
return any(phrase in error_message.lower() for phrase in context_limit_phrases)
class LLM:
"""
Easy to use wrapper for language models. Supports multiple providers like OpenAI,
Anthropic, and others through LiteLLM.
"""
# Default window sizes for different models (75% of actual to be safe)
MODEL_WINDOWS = {
# OpenAI
"gpt-4": 6144, # 8,192 actual
"gpt-4o": 96000, # 128,000 actual
"gpt-4o-mini": 96000, # 128,000 actual
"gpt-4-turbo": 96000, # 128,000 actual
"o1-preview": 96000, # 128,000 actual
"o1-mini": 96000, # 128,000 actual
# Anthropic
"claude-3-5-sonnet": 12288, # 16,384 actual
"claude-3-sonnet": 12288, # 16,384 actual
"claude-3-opus": 96000, # 128,000 actual
"claude-3-haiku": 96000, # 128,000 actual
# Gemini
"gemini-2.0-flash": 786432, # 1,048,576 actual
"gemini-1.5-pro": 1572864, # 2,097,152 actual
"gemini-1.5-flash": 786432, # 1,048,576 actual
"gemini-1.5-flash-8b": 786432, # 1,048,576 actual
# Deepseek
"deepseek-chat": 96000, # 128,000 actual
# Groq
"gemma2-9b-it": 6144, # 8,192 actual
"gemma-7b-it": 6144, # 8,192 actual
"llama3-70b-8192": 6144, # 8,192 actual
"llama3-8b-8192": 6144, # 8,192 actual
"mixtral-8x7b-32768": 24576, # 32,768 actual
"llama-3.3-70b-versatile": 96000, # 128,000 actual
"llama-3.3-70b-instruct": 96000, # 128,000 actual
# Other llama models
"llama-3.1-70b-versatile": 98304, # 131,072 actual
"llama-3.1-8b-instant": 98304, # 131,072 actual
"llama-3.2-1b-preview": 6144, # 8,192 actual
"llama-3.2-3b-preview": 6144, # 8,192 actual
"llama-3.2-11b-text-preview": 6144, # 8,192 actual
"llama-3.2-90b-text-preview": 6144 # 8,192 actual
}
def __init__(
self,
model: str,
timeout: Optional[int] = None,
temperature: Optional[float] = None,
top_p: Optional[float] = None,
n: Optional[int] = None,
max_tokens: Optional[int] = None,
presence_penalty: Optional[float] = None,
frequency_penalty: Optional[float] = None,
logit_bias: Optional[Dict[int, float]] = None,
response_format: Optional[Dict[str, Any]] = None,
seed: Optional[int] = None,
logprobs: Optional[bool] = None,
top_logprobs: Optional[int] = None,
api_version: Optional[str] = None,
stop_phrases: Optional[Union[str, List[str]]] = None,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
events: List[Any] = [],
**extra_settings
):
try:
import litellm
# Set litellm options globally
litellm.set_verbose = False
litellm.success_callback = []
litellm._async_success_callback = []
litellm.callbacks = []
# Additional logging suppression
litellm.suppress_debug_messages = True
logging.getLogger("litellm.utils").setLevel(logging.WARNING)
logging.getLogger("litellm.main").setLevel(logging.WARNING)
except ImportError:
raise ImportError(
"LiteLLM is required but not installed. "
"Please install with: pip install 'praisonaiagents[llm]'"
)
self.model = model
self.timeout = timeout
self.temperature = temperature
self.top_p = top_p
self.n = n
self.max_tokens = max_tokens
self.presence_penalty = presence_penalty
self.frequency_penalty = frequency_penalty
self.logit_bias = logit_bias
self.response_format = response_format
self.seed = seed
self.logprobs = logprobs
self.top_logprobs = top_logprobs
self.api_version = api_version
self.stop_phrases = stop_phrases
self.api_key = api_key
self.base_url = base_url
self.events = events
self.extra_settings = extra_settings
self.console = Console()
self.chat_history = []
self.verbose = extra_settings.get('verbose', True)
self.markdown = extra_settings.get('markdown', True)
self.self_reflect = extra_settings.get('self_reflect', False)
self.max_reflect = extra_settings.get('max_reflect', 3)
self.min_reflect = extra_settings.get('min_reflect', 1)
# Enable error dropping for cleaner output
litellm.drop_params = True
self._setup_event_tracking(events)
def get_response(
self,
prompt: Union[str, List[Dict]],
system_prompt: Optional[str] = None,
chat_history: Optional[List[Dict]] = None,
temperature: float = 0.2,
tools: Optional[List[Any]] = None,
output_json: Optional[BaseModel] = None,
output_pydantic: Optional[BaseModel] = None,
verbose: bool = True,
markdown: bool = True,
self_reflect: bool = False,
max_reflect: int = 3,
min_reflect: int = 1,
console: Optional[Console] = None,
agent_name: Optional[str] = None,
agent_role: Optional[str] = None,
agent_tools: Optional[List[str]] = None,
execute_tool_fn: Optional[Callable] = None,
**kwargs
) -> str:
"""Enhanced get_response with all OpenAI-like features"""
try:
import litellm
# Disable litellm debug messages
litellm.set_verbose = False
# Build messages list
messages = []
if 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())}"
messages.append({"role": "system", "content": system_prompt})
if chat_history:
messages.extend(chat_history)
# Handle prompt modifications for JSON output
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 item in prompt:
if item["type"] == "text":
item["text"] += "\nReturn ONLY a valid JSON object. No other text or explanation."
break
# Add prompt to messages
if isinstance(prompt, list):
messages.append({"role": "user", "content": prompt})
else:
messages.append({"role": "user", "content": prompt})
start_time = time.time()
reflection_count = 0
while True:
try:
if verbose:
display_text = prompt
if isinstance(prompt, list):
display_text = next((item["text"] for item in prompt if item["type"] == "text"), "")
if display_text and str(display_text).strip():
display_instruction(
f"Agent {agent_name} is processing prompt: {display_text}",
console=console,
agent_name=agent_name,
agent_role=agent_role,
agent_tools=agent_tools
)
# Get response from LiteLLM
start_time = time.time()
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
response_text = ""
for chunk in litellm.completion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
response_text += content
live.update(display_generating(response_text, start_time))
else:
# Non-verbose mode, just collect the response
response_text = ""
for chunk in litellm.completion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
response_text = response_text.strip()
# Get final completion to check for tool calls
final_response = litellm.completion(
model=self.model,
messages=messages,
temperature=temperature,
stream=False, # No streaming for tool call check
**kwargs
)
tool_calls = final_response["choices"][0]["message"].get("tool_calls")
# Handle tool calls
if tool_calls and execute_tool_fn:
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 verbose:
display_tool_call(f"Agent {agent_name} is calling function '{function_name}' with arguments: {arguments}", console=console)
tool_result = execute_tool_fn(function_name, arguments)
if tool_result:
if verbose:
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=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"
})
# Get response after tool calls with streaming
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
response_text = ""
for chunk in litellm.completion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
response_text += content
live.update(display_generating(response_text, start_time))
else:
response_text = ""
for chunk in litellm.completion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
response_text = response_text.strip()
# Handle output formatting
if output_json or output_pydantic:
self.chat_history.append({"role": "user", "content": original_prompt})
self.chat_history.append({"role": "assistant", "content": response_text})
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
if not self_reflect:
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
# Handle self-reflection
reflection_prompt = f"""
Reflect on your previous response: '{response_text}'.
Identify any flaws, improvements, or actions.
Provide a "satisfactory" status ('yes' or 'no').
Output MUST be JSON with 'reflection' and 'satisfactory'.
"""
reflection_messages = messages + [
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt}
]
# Get reflection response with streaming
if verbose:
with Live(display_generating("", start_time), console=console, refresh_per_second=4) as live:
reflection_text = ""
for chunk in litellm.completion(
model=self.model,
messages=reflection_messages,
temperature=temperature,
stream=True,
response_format={"type": "json_object"}
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
reflection_text += content
live.update(display_generating(reflection_text, start_time))
else:
reflection_text = ""
for chunk in litellm.completion(
model=self.model,
messages=reflection_messages,
temperature=temperature,
stream=True,
response_format={"type": "json_object"}
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
reflection_text += chunk.choices[0].delta.content
try:
reflection_data = json.loads(reflection_text)
satisfactory = reflection_data.get("satisfactory", "no").lower() == "yes"
if verbose:
display_self_reflection(
f"Agent {agent_name} self reflection: reflection='{reflection_data['reflection']}' satisfactory='{reflection_data['satisfactory']}'",
console=console
)
if satisfactory and reflection_count >= min_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
if reflection_count >= max_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
reflection_count += 1
messages.extend([
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt},
{"role": "assistant", "content": reflection_text},
{"role": "user", "content": "Now regenerate your response using the reflection you made"}
])
continue
except json.JSONDecodeError:
reflection_count += 1
if reflection_count >= max_reflect:
return response_text
continue
except Exception as e:
display_error(f"Error in LLM response: {str(e)}")
return None
except Exception as error:
display_error(f"Error in get_response: {str(error)}")
raise
async def get_response_async(
self,
prompt: Union[str, List[Dict]],
system_prompt: Optional[str] = None,
chat_history: Optional[List[Dict]] = None,
temperature: float = 0.2,
tools: Optional[List[Any]] = None,
output_json: Optional[BaseModel] = None,
output_pydantic: Optional[BaseModel] = None,
verbose: bool = True,
markdown: bool = True,
self_reflect: bool = False,
max_reflect: int = 3,
min_reflect: int = 1,
console: Optional[Console] = None,
agent_name: Optional[str] = None,
agent_role: Optional[str] = None,
agent_tools: Optional[List[str]] = None,
execute_tool_fn: Optional[Callable] = None,
**kwargs
) -> str:
"""Async version of get_response with identical functionality."""
try:
import litellm
litellm.set_verbose = False
# Build messages list
messages = []
if 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())}"
messages.append({"role": "system", "content": system_prompt})
if chat_history:
messages.extend(chat_history)
# Handle prompt modifications for JSON output
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 item in prompt:
if item["type"] == "text":
item["text"] += "\nReturn ONLY a valid JSON object. No other text or explanation."
break
# Add prompt to messages
if isinstance(prompt, list):
messages.append({"role": "user", "content": prompt})
else:
messages.append({"role": "user", "content": prompt})
start_time = time.time()
reflection_count = 0
# Format tools for LiteLLM
formatted_tools = None
if tools:
logging.info(f"Starting tool formatting for {len(tools)} tools")
formatted_tools = []
for tool in tools:
logging.info(f"Processing tool: {tool.__name__ if hasattr(tool, '__name__') else str(tool)}")
if hasattr(tool, '__name__'):
tool_name = tool.__name__
tool_doc = tool.__doc__ or "No description available"
# Get function signature
import inspect
sig = inspect.signature(tool)
logging.debug(f"Tool signature: {sig}")
params = {}
required = []
for name, param in sig.parameters.items():
logging.debug(f"Processing parameter: {name} with annotation: {param.annotation}")
param_type = "string"
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 == Dict:
param_type = "object"
elif param.annotation == List:
param_type = "array"
elif hasattr(param.annotation, "__name__"):
param_type = param.annotation.__name__.lower()
params[name] = {"type": param_type}
if param.default == inspect.Parameter.empty:
required.append(name)
logging.debug(f"Generated parameters: {params}")
logging.debug(f"Required parameters: {required}")
tool_def = {
"type": "function",
"function": {
"name": tool_name,
"description": tool_doc,
"parameters": {
"type": "object",
"properties": params,
"required": required
}
}
}
# Ensure tool definition is JSON serializable
print(f"Generated tool definition: {tool_def}")
try:
json.dumps(tool_def) # Test serialization
logging.info(f"Generated tool definition: {tool_def}")
formatted_tools.append(tool_def)
except TypeError as e:
logging.error(f"Tool definition not JSON serializable: {e}")
continue
# Validate final tools list
if formatted_tools:
try:
json.dumps(formatted_tools) # Final serialization check
logging.info(f"Final formatted tools: {json.dumps(formatted_tools, indent=2)}")
except TypeError as e:
logging.error(f"Final tools list not JSON serializable: {e}")
formatted_tools = None
response_text = ""
if verbose:
# ----------------------------------------------------
# 1) Make the streaming call WITHOUT tools
# ----------------------------------------------------
async for chunk in await litellm.acompletion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
print("\033[K", end="\r")
print(f"Generating... {time.time() - start_time:.1f}s", end="\r")
else:
# Non-verbose streaming call, still no tools
async for chunk in await litellm.acompletion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
response_text = response_text.strip()
# ----------------------------------------------------
# 2) If tool calls are needed, do a non-streaming call
# ----------------------------------------------------
if tools and execute_tool_fn:
# Next call with tools if needed
tool_response = await litellm.acompletion(
model=self.model,
messages=messages,
temperature=temperature,
stream=False,
tools=formatted_tools, # We safely pass tools here
**kwargs
)
# handle tool_calls from tool_response as usual...
tool_calls = tool_response.choices[0].message.get("tool_calls")
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 verbose:
display_tool_call(f"Agent {agent_name} is calling function '{function_name}' with arguments: {arguments}", console=console)
tool_result = await execute_tool_fn(function_name, arguments)
if tool_result:
if verbose:
display_tool_call(f"Function '{function_name}' returned: {tool_result}", console=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"
})
# Get response after tool calls with streaming
response_text = ""
if verbose:
async for chunk in await litellm.acompletion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
tools=formatted_tools,
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
response_text += content
print("\033[K", end="\r")
print(f"Reflecting... {time.time() - start_time:.1f}s", end="\r")
else:
response_text = ""
for chunk in litellm.completion(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
response_text = response_text.strip()
# Handle output formatting
if output_json or output_pydantic:
self.chat_history.append({"role": "user", "content": original_prompt})
self.chat_history.append({"role": "assistant", "content": response_text})
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
if not self_reflect:
if verbose:
display_interaction(original_prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
# Handle self-reflection
reflection_prompt = f"""
Reflect on your previous response: '{response_text}'.
Identify any flaws, improvements, or actions.
Provide a "satisfactory" status ('yes' or 'no').
Output MUST be JSON with 'reflection' and 'satisfactory'.
"""
reflection_messages = messages + [
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt}
]
# Get reflection response
reflection_text = ""
if verbose:
async for chunk in await litellm.acompletion(
model=self.model,
messages=reflection_messages,
temperature=temperature,
stream=True,
response_format={"type": "json_object"},
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
reflection_text += content
print("\033[K", end="\r")
print(f"Reflecting... {time.time() - start_time:.1f}s", end="\r")
else:
async for chunk in await litellm.acompletion(
model=self.model,
messages=reflection_messages,
temperature=temperature,
stream=True,
response_format={"type": "json_object"},
**kwargs
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
reflection_text += chunk.choices[0].delta.content
while True: # Add loop for reflection handling
try:
reflection_data = json.loads(reflection_text)
satisfactory = reflection_data.get("satisfactory", "no").lower() == "yes"
if verbose:
display_self_reflection(
f"Agent {agent_name} self reflection: reflection='{reflection_data['reflection']}' satisfactory='{reflection_data['satisfactory']}'",
console=console
)
if satisfactory and reflection_count >= min_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
if reflection_count >= max_reflect - 1:
if verbose:
display_interaction(prompt, response_text, markdown=markdown,
generation_time=time.time() - start_time, console=console)
return response_text
reflection_count += 1
messages.extend([
{"role": "assistant", "content": response_text},
{"role": "user", "content": reflection_prompt},
{"role": "assistant", "content": reflection_text},
{"role": "user", "content": "Now regenerate your response using the reflection you made"}
])
continue # Now properly in a loop
except json.JSONDecodeError:
reflection_count += 1
if reflection_count >= max_reflect:
return response_text
continue # Now properly in a loop
except Exception as error:
if LLMContextLengthExceededException(str(error))._is_context_limit_error(str(error)):
raise LLMContextLengthExceededException(str(error))
display_error(f"Error in get_response_async: {str(error)}")
raise
def can_use_tools(self) -> bool:
"""Check if this model can use tool functions"""
try:
import litellm
allowed_params = litellm.get_supported_openai_params(model=self.model)
return "response_format" in allowed_params
except ImportError:
raise ImportError(
"LiteLLM is required but not installed. "
"Please install it with: pip install 'praisonaiagents[llm]'"
)
except:
return False
def can_use_stop_words(self) -> bool:
"""Check if this model supports stop words"""
try:
import litellm
allowed_params = litellm.get_supported_openai_params(model=self.model)
return "stop" in allowed_params
except ImportError:
raise ImportError(
"LiteLLM is required but not installed. "
"Please install it with: pip install 'praisonaiagents[llm]'"
)
except:
return False
def get_context_size(self) -> int:
"""Get safe input size limit for this model"""
for model_prefix, size in self.MODEL_WINDOWS.items():
if self.model.startswith(model_prefix):
return size
return 4000 # Safe default
def _setup_event_tracking(self, events: List[Any]) -> None:
"""Setup callback functions for tracking model usage"""
try:
import litellm
except ImportError:
raise ImportError(
"LiteLLM is required but not installed. "
"Please install it with: pip install 'praisonaiagents[llm]'"
)
event_types = [type(event) for event in events]
# Remove old events of same type
for event in litellm.success_callback[:]:
if type(event) in event_types:
litellm.success_callback.remove(event)
for event in litellm._async_success_callback[:]:
if type(event) in event_types:
litellm._async_success_callback.remove(event)
litellm.callbacks = events
+14 -1
View File
@@ -14,6 +14,15 @@ from rich.logging import RichHandler
from rich.live import Live
import asyncio
# # Configure root logger
# logging.basicConfig(level=logging.WARNING)
# Suppress litellm logs
logging.getLogger("litellm").handlers = []
logging.getLogger("litellm.utils").handlers = []
logging.getLogger("litellm").propagate = False
logging.getLogger("litellm.utils").propagate = False
LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
logging.basicConfig(
@@ -23,6 +32,10 @@ logging.basicConfig(
handlers=[RichHandler(rich_tracebacks=True)]
)
# Add these lines to suppress markdown parser debug logs
logging.getLogger('markdown_it').setLevel(logging.WARNING)
logging.getLogger('rich.markdown').setLevel(logging.WARNING)
# Global list to store error logs
error_logs = []
@@ -340,7 +353,7 @@ class ReflectionOutput(BaseModel):
reflection: str
satisfactory: Literal["yes", "no"]
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
client = OpenAI(api_key=(os.environ["OPENAI_API_KEY"] if os.environ.get("OPENAI_API_KEY") else "xxxx"))
class TaskOutput(BaseModel):
description: str
+1 -1
View File
@@ -15,7 +15,7 @@ try:
CHROMADB_AVAILABLE = True
except ImportError:
CHROMADB_AVAILABLE = False
logger.warning("To use memory features, please run: pip install \"praisonaiagents[memory]\"")
pass
try:
import mem0
+157 -76
View File
@@ -5,6 +5,8 @@ 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]
@@ -62,46 +64,47 @@ class Process:
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
)
# # 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}
# # 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
)
# 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}"
# 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}"
@@ -144,13 +147,17 @@ Return a JSON object with an 'items' array containing the items to process.
next_task = None
if current_task and current_task.result:
if current_task.task_type in ["decision", "loop"]:
result = current_task.result.raw.lower()
# 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() in result:
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": # If empty or explicit exit
if not task_value or task_value == "exit":
logging.info("Workflow exit condition met, ending workflow")
current_task = None
break
@@ -322,7 +329,76 @@ Provide a JSON with the structure:
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
@@ -346,40 +422,41 @@ Provide a JSON with the structure:
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
)
# # 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}
# # 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
)
# 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}"
# 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}"
@@ -396,7 +473,7 @@ Return a JSON object with an 'items' array containing the items to process.
yield task_id
visited_tasks.add(task_id)
# Reset completed task to "not started" so it can run again
# 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"
@@ -422,13 +499,17 @@ Return a JSON object with an 'items' array containing the items to process.
next_task = None
if current_task and current_task.result:
if current_task.task_type in ["decision", "loop"]:
result = current_task.result.raw.lower()
# 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() in result:
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": # If empty or explicit exit
if not task_value or task_value == "exit":
logging.info("Workflow exit condition met, ending workflow")
current_task = None
break
+87 -4
View File
@@ -1,6 +1,6 @@
import logging
import asyncio
from typing import List, Optional, Dict, Any, Type, Callable, Union, Coroutine
from typing import List, Optional, Dict, Any, Type, Callable, Union, Coroutine, Literal
from pydantic import BaseModel
from ..main import TaskOutput
from ..agent.agent import Agent
@@ -19,7 +19,7 @@ class Task:
agent: Optional[Agent] = None,
name: Optional[str] = None,
tools: Optional[List[Any]] = None,
context: Optional[List["Task"]] = None,
context: Optional[List[Union[str, List, 'Task']]] = None,
async_execution: Optional[bool] = False,
config: Optional[Dict[str, Any]] = None,
output_file: Optional[str] = None,
@@ -37,8 +37,21 @@ class Task:
is_start: bool = False,
loop_state: Optional[Dict[str, Union[str, int]]] = None,
memory=None,
quality_check=True
quality_check=True,
input_file: Optional[str] = None
):
# Add check if memory config is provided
if memory is not None or (config and config.get('memory_config')):
try:
from ..memory.memory import Memory
MEMORY_AVAILABLE = True
except ImportError:
raise ImportError(
"Memory features requested in Task but memory dependencies not installed. "
"Please install with: pip install \"praisonaiagents[memory]\""
)
self.input_file = input_file
self.id = str(uuid.uuid4()) if id is None else str(id)
self.name = name
self.description = description
@@ -83,6 +96,47 @@ class Task:
# Track previous tasks based on next_tasks relationships
self.previous_tasks = []
# If task_type="decision" and output_pydantic is not set
if self.task_type == "decision" and not self.output_pydantic:
from pydantic import BaseModel
from typing import Literal
# Gather condition keys for the "decision" field
condition_keys = list(self.condition.keys())
if not condition_keys:
# Fall back to placeholders if nothing is specified
condition_keys = ["next_task", "exit"]
# Create a dynamic literal type from condition keys
DecisionLiteral = Literal.__getitem__(tuple(condition_keys))
class DecisionModel(BaseModel):
response: str
decision: DecisionLiteral
self.output_pydantic = DecisionModel
# If task_type="loop" and output_pydantic is not set
if self.task_type == "loop" and not self.output_pydantic:
from pydantic import BaseModel
from typing import Literal
# Gather condition keys for the "decision" field
condition_keys = list(self.condition.keys())
if not condition_keys:
# Fall back to placeholders if nothing is specified
condition_keys = ["next_item", "exit"]
# Create a dynamic literal type
LoopLiteral = Literal.__getitem__(tuple(condition_keys))
class LoopModel(BaseModel):
response: str
decision: LoopLiteral
loop_id: str # Additional field for loop
self.output_pydantic = LoopModel
def __str__(self):
return f"Task(name='{self.name if self.name else 'None'}', description='{self.description}', agent='{self.agent.name if self.agent else 'None'}', status='{self.status}')"
@@ -219,4 +273,33 @@ class Task:
self.callback(task_output)
except Exception as e:
logger.error(f"Task {self.id}: Failed to execute callback: {e}")
logger.exception(e)
logger.exception(e)
task_prompt = f"""
You need to do the following task: {self.description}.
Expected Output: {self.expected_output}.
"""
if self.context:
context_results = [] # Use list to avoid duplicates
for context_item in self.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Context:
{' '.join(unique_contexts)}
"""
+9 -2
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.0.39"
version = "0.0.50"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
authors = [
{ name="Mervin Praison" }
@@ -27,8 +27,15 @@ knowledge = [
"chonkie"
]
# Add LLM dependencies
llm = [
"litellm>=1.50.0",
"pydantic>=2.4.2"
]
# Combined features
all = [
"praisonaiagents[memory]",
"praisonaiagents[knowledge]"
"praisonaiagents[knowledge]",
"praisonaiagents[llm]"
]
+22
View File
@@ -0,0 +1,22 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
agent = Agent(
instructions="You are a loop agent that creating a loop of tasks.",
llm="gpt-4o-mini"
)
task = Task(
description="Create the list of tasks to be looped through.",
agent=agent,
task_type="loop",
input_file="tasks.csv"
)
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
process="workflow",
max_iter=30
)
agents.start()
+139
View File
@@ -0,0 +1,139 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from praisonaiagents.tools import read_csv, write_csv
import pandas as pd
def read_csv_smart(csv_path: str) -> pd.DataFrame:
"""Read CSV and use first column as task, handling both header/no-header cases"""
# Try reading with headers first
df = pd.read_csv(csv_path)
# Check if first row looks like data
if not any(col.lower() in ['task', 'description', 'status', 'state'] for col in df.columns):
# If no header-like names found, read without headers
df = pd.read_csv(csv_path, header=None)
# Rename columns consistently
df.columns = [*['task'], *[f'col_{i}' for i in range(1, len(df.columns))]]
if 'status' not in df.columns:
df['status'] = 'pending'
if 'loop_id' not in df.columns:
# Start loop_id from 1 instead of 0
df['loop_id'] = (df.index + 1).astype(str)
return df[['task', 'status', 'loop_id']]
def has_pending_tasks(df: pd.DataFrame) -> bool:
"""Check if there are any pending tasks in the DataFrame"""
return not df[df['status'] == 'pending'].empty
def check_task_status(csv_path: str) -> dict:
"""Read task status from CSV file"""
try:
# Always read directly from CSV file
df = pd.read_csv(csv_path, keep_default_na=False)
# Get only pending tasks from original status
pending_tasks = df[df['status'].str.lower() == 'pending']
if not pending_tasks.empty:
task_data = pending_tasks.iloc[0].to_dict()
return {
'has_pending': True,
'next_task': task_data
}
return {'has_pending': False, 'next_task': None}
except Exception as e:
print(f"Error reading CSV: {e}")
return {'has_pending': False, 'next_task': None, 'error': str(e)}
def get_next_task() -> dict:
"""Get the next pending task from CSV"""
status = check_task_status("tasks.csv")
if status['has_pending'] and status['next_task']:
task = status['next_task']
if task['status'].lower() == 'pending':
return {
'loop_data': {
'task': task['task'],
'loop_id': task['loop_id'],
'status': task['status']
}
}
return None
def update_task_status(loop_id: str, new_status: str) -> bool:
"""Update task status in CSV file using loop_id as identifier"""
try:
# Read directly from CSV file
df = pd.read_csv("tasks.csv", keep_default_na=False)
df['loop_id'] = df['loop_id'].astype(str)
mask = df['loop_id'] == str(loop_id)
if mask.any():
df.loc[mask, 'status'] = new_status
df.to_csv("tasks.csv", index=False)
return True
print(f"No task found with loop_id: {loop_id}")
return False
except Exception as e:
print(f"Error updating status: {e}")
return False
identify_agent = Agent(
name="Identify Agent",
role="Pending Task Identifier",
goal="Identify the next pending task",
tools=[get_next_task],
llm="gpt-4o-mini"
)
# Create the repetitive agent
repetitive_agent = Agent(
name="TaskProcessor",
role="Task Processing Specialist",
goal="Complete the task response",
llm="gpt-4o-mini"
)
update_status_agent = Agent(
name="UpdateStatusAgent",
role="Status Updater",
goal="Update the status of the task in CSV",
tools=[update_task_status],
llm="gpt-4o-mini"
)
# Define the repetitive task
identify_task = Task(
name="identify_task",
description="Identify the next pending task. If there are no pending tasks decision is completed.",
agent=identify_agent,
task_type="loop",
condition={
"pending": ["process_task"],
"completed": "exit"
}
)
process_task = Task(
name="process_task",
description="Complete the task mentioned in the response",
agent=repetitive_agent,
context=[identify_task],
task_type="loop",
next_tasks=["update_task"]
)
update_task = Task(
name="update_task",
description="Update the task status",
agent=update_status_agent,
next_tasks= ["identify_task"]
)
# Create and run agents manager
agents = PraisonAIAgents(
agents=[identify_agent, repetitive_agent],
tasks=[identify_task, process_task, update_task],
process="workflow"
)
agents.start()
+15
View File
@@ -0,0 +1,15 @@
# Core dependencies
pydantic
rich
openai>=1.30.0
# Memory dependencies
chromadb>=0.5.23
# Knowledge dependencies
mem0ai>=0.1.0
markitdown
chonkie
# Development dependencies
python-dotenv>=0.19.0
+100
View File
@@ -0,0 +1,100 @@
Write a product description for a smartwatch in 2 lines.
Create a user manual for a blender in 2 lines.
Draft an apology email for delayed delivery in 2 lines.
Write a blog post on "Benefits of Meditation" in 2 lines.
Create a privacy policy for a website in 2 lines.
Write instructions for setting up a Wi-Fi router in 2 lines.
Draft an email to follow up after a job interview in 2 lines.
Create a FAQ page for an e-commerce store in 2 lines.
Write an invitation email for a webinar in 2 lines.
Create a terms and conditions page for an app in 2 lines.
Write a press release for a product launch in 2 lines.
Create a checklist for house cleaning tasks in 2 lines.
Draft a resignation letter template in 2 lines.
Write a cover letter for a software developer role in 2 lines.
Create onboarding instructions for new employees in 2 lines.
Write a memo announcing a new policy in a company in 2 lines.
Create a safety guidelines document for a workplace in 2 lines.
Write a pitch email to potential investors in 2 lines.
Draft a thank-you email for attending a conference in 2 lines.
Create a refund policy template for an online store in 2 lines.
Write a blog on "How to Improve Time Management" in 2 lines.
Create step-by-step instructions for changing a car tyre in 2 lines.
Write a welcome email for new subscribers in 2 lines.
Draft an event agenda template in 2 lines.
Create a code of conduct for an online forum in 2 lines.
Write a guide for beginners to start a blog in 2 lines.
Create a checklist for organising a party in 2 lines.
Draft an email to request a product review in 2 lines.
Write a policy for remote work in a company in 2 lines.
Create a simple tutorial for using Excel formulas in 2 lines.
Write a thank-you letter for a donation in 2 lines.
Draft a meeting minutes template in 2 lines.
Create an FAQ for a gym membership in 2 lines.
Write a blog post about "Healthy Snacks for Kids" in 2 lines.
Create a guide for securing your social media accounts in 2 lines.
Draft an email to request a testimonial from a client in 2 lines.
Write a safety checklist for camping trips in 2 lines.
Create a script for a customer service call in 2 lines.
Write a tutorial for creating a simple PowerPoint presentation in 2 lines.
Create a packing list for a beach vacation in 2 lines.
Draft an email to cancel a service subscription in 2 lines.
Write a personal statement for university admission in 2 lines.
Create a template for tracking monthly expenses in 2 lines.
Write a guide for planting and caring for succulents in 2 lines.
Create a simple user guide for a mobile app in 2 lines.
Draft an email to announce a team-building activity in 2 lines.
Write a step-by-step guide for baking a cake in 2 lines.
Create a list of house maintenance tasks in 2 lines.
Draft a partnership proposal email in 2 lines.
Write a guide for basic photography tips in 2 lines.
Create a feedback form template for an online course in 2 lines.
Write a blog on "Top 5 Budget Travel Destinations" in 2 lines.
Draft a letter of recommendation for a colleague in 2 lines.
Create a workout plan for beginners in 2 lines.
Write a guide for troubleshooting common tech issues in 2 lines.
Draft a reminder email for an upcoming appointment in 2 lines.
Create a guide for setting personal goals in 2 lines.
Write a blog post about "How to Start Freelancing" in 2 lines.
Create a template for event planning in 2 lines.
Draft an email to notify users about system maintenance in 2 lines.
Write a guide for choosing the right laptop in 2 lines.
Create a checklist for moving to a new house in 2 lines.
Draft an email to update a client on project status in 2 lines.
Write a guide for reducing screen time in 2 lines.
Create a shopping list template for weekly groceries in 2 lines.
Draft a thank-you email for completing a survey in 2 lines.
Write a blog on "Simple DIY Crafts for Beginners" in 2 lines.
Create a checklist for starting a small business in 2 lines.
Draft an email to apologise for a customer complaint in 2 lines.
Write a guide for setting up a personal budget in 2 lines.
Create a policy for using company-provided equipment in 2 lines.
Draft an email to notify about a price increase in 2 lines.
Write a tutorial for creating a resume using Word in 2 lines.
Create a simple guide for organising a charity event in 2 lines.
Draft a formal invitation letter for a conference in 2 lines.
Write a blog post about "Top Productivity Apps" in 2 lines.
Create a checklist for first-time pet owners in 2 lines.
Draft an email to confirm a service appointment in 2 lines.
Write a beginner’s guide for learning to code in 2 lines.
Create a guide for assembling a basic toolkit in 2 lines.
Draft a welcome email for a new team member in 2 lines.
Write a guide for preparing a home for winter in 2 lines.
Create a schedule template for meal planning in 2 lines.
Draft an email to request feedback from a customer in 2 lines.
Write a guide on "How to Build a Morning Routine" in 2 lines.
Create a checklist for hosting a virtual meeting in 2 lines.
Draft a newsletter for a non-profit organisation in 2 lines.
Write a guide for beginners to use Canva in 2 lines.
Create a guide for organising your workspace in 2 lines.
Draft an email to invite users to a beta program in 2 lines.
Write a step-by-step guide for creating a podcast in 2 lines.
Create a simple guide for buying your first car in 2 lines.
Draft an email to announce a new team member in 2 lines.
Write a tutorial on creating basic charts in Excel in 2 lines.
Create a guide for teaching basic first aid in 2 lines.
Draft an email to follow up after a sales call in 2 lines.
Write a blog post on "How to Save Money on Utilities" in 2 lines.
Create a guide for designing a basic website in 2 lines.
Draft a thank-you email for a business referral in 2 lines.
Write a guide for setting up a new smartphone in 2 lines.
Can't render this file because it contains an unexpected character in line 4 and column 22.
+516 -4
View File
@@ -6,6 +6,89 @@ resolution-markers = [
"python_full_version < '3.12'",
]
[[package]]
name = "aiohappyeyeballs"
version = "2.4.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7f/55/e4373e888fdacb15563ef6fa9fa8c8252476ea071e96fb46defac9f18bf2/aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745", size = 21977 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8", size = 14756 },
]
[[package]]
name = "aiohttp"
version = "3.11.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohappyeyeballs" },
{ name = "aiosignal" },
{ name = "attrs" },
{ name = "frozenlist" },
{ name = "multidict" },
{ name = "propcache" },
{ name = "yarl" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fe/ed/f26db39d29cd3cb2f5a3374304c713fe5ab5a0e4c8ee25a0c45cc6adf844/aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", size = 7669618 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/34/ae/e8806a9f054e15f1d18b04db75c23ec38ec954a10c0a68d3bd275d7e8be3/aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", size = 708624 },
{ url = "https://files.pythonhosted.org/packages/c7/e0/313ef1a333fb4d58d0c55a6acb3cd772f5d7756604b455181049e222c020/aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", size = 468507 },
{ url = "https://files.pythonhosted.org/packages/a9/60/03455476bf1f467e5b4a32a465c450548b2ce724eec39d69f737191f936a/aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", size = 455571 },
{ url = "https://files.pythonhosted.org/packages/be/f9/469588603bd75bf02c8ffb8c8a0d4b217eed446b49d4a767684685aa33fd/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", size = 1685694 },
{ url = "https://files.pythonhosted.org/packages/88/b9/1b7fa43faf6c8616fa94c568dc1309ffee2b6b68b04ac268e5d64b738688/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", size = 1743660 },
{ url = "https://files.pythonhosted.org/packages/2a/8b/0248d19dbb16b67222e75f6aecedd014656225733157e5afaf6a6a07e2e8/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", size = 1785421 },
{ url = "https://files.pythonhosted.org/packages/c4/11/f478e071815a46ca0a5ae974651ff0c7a35898c55063305a896e58aa1247/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", size = 1675145 },
{ url = "https://files.pythonhosted.org/packages/26/5d/284d182fecbb5075ae10153ff7374f57314c93a8681666600e3a9e09c505/aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", size = 1619804 },
{ url = "https://files.pythonhosted.org/packages/1b/78/980064c2ad685c64ce0e8aeeb7ef1e53f43c5b005edcd7d32e60809c4992/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", size = 1654007 },
{ url = "https://files.pythonhosted.org/packages/21/8d/9e658d63b1438ad42b96f94da227f2e2c1d5c6001c9e8ffcc0bfb22e9105/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", size = 1650022 },
{ url = "https://files.pythonhosted.org/packages/85/fd/a032bf7f2755c2df4f87f9effa34ccc1ef5cea465377dbaeef93bb56bbd6/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", size = 1732899 },
{ url = "https://files.pythonhosted.org/packages/c5/0c/c2b85fde167dd440c7ba50af2aac20b5a5666392b174df54c00f888c5a75/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", size = 1755142 },
{ url = "https://files.pythonhosted.org/packages/bc/78/91ae1a3b3b3bed8b893c5d69c07023e151b1c95d79544ad04cf68f596c2f/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", size = 1692736 },
{ url = "https://files.pythonhosted.org/packages/77/89/a7ef9c4b4cdb546fcc650ca7f7395aaffbd267f0e1f648a436bec33c9b95/aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", size = 416418 },
{ url = "https://files.pythonhosted.org/packages/fc/db/2192489a8a51b52e06627506f8ac8df69ee221de88ab9bdea77aa793aa6a/aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", size = 442509 },
{ url = "https://files.pythonhosted.org/packages/69/cf/4bda538c502f9738d6b95ada11603c05ec260807246e15e869fc3ec5de97/aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", size = 704666 },
{ url = "https://files.pythonhosted.org/packages/46/7b/87fcef2cad2fad420ca77bef981e815df6904047d0a1bd6aeded1b0d1d66/aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", size = 464057 },
{ url = "https://files.pythonhosted.org/packages/5a/a6/789e1f17a1b6f4a38939fbc39d29e1d960d5f89f73d0629a939410171bc0/aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", size = 455996 },
{ url = "https://files.pythonhosted.org/packages/b7/dd/485061fbfef33165ce7320db36e530cd7116ee1098e9c3774d15a732b3fd/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a", size = 1682367 },
{ url = "https://files.pythonhosted.org/packages/e9/d7/9ec5b3ea9ae215c311d88b2093e8da17e67b8856673e4166c994e117ee3e/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231", size = 1736989 },
{ url = "https://files.pythonhosted.org/packages/d6/fb/ea94927f7bfe1d86178c9d3e0a8c54f651a0a655214cce930b3c679b8f64/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e", size = 1793265 },
{ url = "https://files.pythonhosted.org/packages/40/7f/6de218084f9b653026bd7063cd8045123a7ba90c25176465f266976d8c82/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8", size = 1691841 },
{ url = "https://files.pythonhosted.org/packages/77/e2/992f43d87831cbddb6b09c57ab55499332f60ad6fdbf438ff4419c2925fc/aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8", size = 1619317 },
{ url = "https://files.pythonhosted.org/packages/96/74/879b23cdd816db4133325a201287c95bef4ce669acde37f8f1b8669e1755/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c", size = 1641416 },
{ url = "https://files.pythonhosted.org/packages/30/98/b123f6b15d87c54e58fd7ae3558ff594f898d7f30a90899718f3215ad328/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab", size = 1646514 },
{ url = "https://files.pythonhosted.org/packages/d7/38/257fda3dc99d6978ab943141d5165ec74fd4b4164baa15e9c66fa21da86b/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da", size = 1702095 },
{ url = "https://files.pythonhosted.org/packages/0c/f4/ddab089053f9fb96654df5505c0a69bde093214b3c3454f6bfdb1845f558/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853", size = 1734611 },
{ url = "https://files.pythonhosted.org/packages/c3/d6/f30b2bc520c38c8aa4657ed953186e535ae84abe55c08d0f70acd72ff577/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e", size = 1694576 },
{ url = "https://files.pythonhosted.org/packages/bc/97/b0a88c3f4c6d0020b34045ee6d954058abc870814f6e310c4c9b74254116/aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600", size = 411363 },
{ url = "https://files.pythonhosted.org/packages/7f/23/cc36d9c398980acaeeb443100f0216f50a7cfe20c67a9fd0a2f1a5a846de/aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d", size = 437666 },
{ url = "https://files.pythonhosted.org/packages/49/d1/d8af164f400bad432b63e1ac857d74a09311a8334b0481f2f64b158b50eb/aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9", size = 697982 },
{ url = "https://files.pythonhosted.org/packages/92/d1/faad3bf9fa4bfd26b95c69fc2e98937d52b1ff44f7e28131855a98d23a17/aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194", size = 460662 },
{ url = "https://files.pythonhosted.org/packages/db/61/0d71cc66d63909dabc4590f74eba71f91873a77ea52424401c2498d47536/aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f", size = 452950 },
{ url = "https://files.pythonhosted.org/packages/07/db/6d04bc7fd92784900704e16b745484ef45b77bd04e25f58f6febaadf7983/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104", size = 1665178 },
{ url = "https://files.pythonhosted.org/packages/54/5c/e95ade9ae29f375411884d9fd98e50535bf9fe316c9feb0f30cd2ac8f508/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff", size = 1717939 },
{ url = "https://files.pythonhosted.org/packages/6f/1c/1e7d5c5daea9e409ed70f7986001b8c9e3a49a50b28404498d30860edab6/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3", size = 1775125 },
{ url = "https://files.pythonhosted.org/packages/5d/66/890987e44f7d2f33a130e37e01a164168e6aff06fce15217b6eaf14df4f6/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1", size = 1677176 },
{ url = "https://files.pythonhosted.org/packages/8f/dc/e2ba57d7a52df6cdf1072fd5fa9c6301a68e1cd67415f189805d3eeb031d/aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4", size = 1603192 },
{ url = "https://files.pythonhosted.org/packages/6c/9e/8d08a57de79ca3a358da449405555e668f2c8871a7777ecd2f0e3912c272/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d", size = 1618296 },
{ url = "https://files.pythonhosted.org/packages/56/51/89822e3ec72db352c32e7fc1c690370e24e231837d9abd056490f3a49886/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87", size = 1616524 },
{ url = "https://files.pythonhosted.org/packages/2c/fa/e2e6d9398f462ffaa095e84717c1732916a57f1814502929ed67dd7568ef/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2", size = 1685471 },
{ url = "https://files.pythonhosted.org/packages/ae/5f/6bb976e619ca28a052e2c0ca7b0251ccd893f93d7c24a96abea38e332bf6/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12", size = 1715312 },
{ url = "https://files.pythonhosted.org/packages/79/c1/756a7e65aa087c7fac724d6c4c038f2faaa2a42fe56dbc1dd62a33ca7213/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5", size = 1672783 },
{ url = "https://files.pythonhosted.org/packages/73/ba/a6190ebb02176c7f75e6308da31f5d49f6477b651a3dcfaaaca865a298e2/aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d", size = 410229 },
{ url = "https://files.pythonhosted.org/packages/b8/62/c9fa5bafe03186a0e4699150a7fed9b1e73240996d0d2f0e5f70f3fdf471/aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99", size = 436081 },
]
[[package]]
name = "aiosignal"
version = "1.3.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "frozenlist" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ba/b5/6d55e80f6d8a08ce22b982eafa278d823b541c925f11ee774b0b9c43473d/aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54", size = 19424 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", size = 7597 },
]
[[package]]
name = "annotated-types"
version = "0.7.0"
@@ -38,6 +121,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828 },
]
[[package]]
name = "attrs"
version = "24.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 },
]
[[package]]
name = "audioop-lts"
version = "0.2.1"
@@ -492,6 +584,60 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/fb/b4/31c461eef98b96b8ab736d97274548eaf2b2e349bf09e4de3902f7d53084/flatbuffers-24.12.23-py2.py3-none-any.whl", hash = "sha256:c418e0d48890f4142b92fd3e343e73a48f194e1f80075ddcc5793779b3585444", size = 30962 },
]
[[package]]
name = "frozenlist"
version = "1.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/79/43/0bed28bf5eb1c9e4301003b74453b8e7aa85fb293b31dde352aac528dafc/frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", size = 94987 },
{ url = "https://files.pythonhosted.org/packages/bb/bf/b74e38f09a246e8abbe1e90eb65787ed745ccab6eaa58b9c9308e052323d/frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", size = 54584 },
{ url = "https://files.pythonhosted.org/packages/2c/31/ab01375682f14f7613a1ade30149f684c84f9b8823a4391ed950c8285656/frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", size = 52499 },
{ url = "https://files.pythonhosted.org/packages/98/a8/d0ac0b9276e1404f58fec3ab6e90a4f76b778a49373ccaf6a563f100dfbc/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", size = 276357 },
{ url = "https://files.pythonhosted.org/packages/ad/c9/c7761084fa822f07dac38ac29f841d4587570dd211e2262544aa0b791d21/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", size = 287516 },
{ url = "https://files.pythonhosted.org/packages/a1/ff/cd7479e703c39df7bdab431798cef89dc75010d8aa0ca2514c5b9321db27/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", size = 283131 },
{ url = "https://files.pythonhosted.org/packages/59/a0/370941beb47d237eca4fbf27e4e91389fd68699e6f4b0ebcc95da463835b/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", size = 261320 },
{ url = "https://files.pythonhosted.org/packages/b8/5f/c10123e8d64867bc9b4f2f510a32042a306ff5fcd7e2e09e5ae5100ee333/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", size = 274877 },
{ url = "https://files.pythonhosted.org/packages/fa/79/38c505601ae29d4348f21706c5d89755ceded02a745016ba2f58bd5f1ea6/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", size = 269592 },
{ url = "https://files.pythonhosted.org/packages/19/e2/39f3a53191b8204ba9f0bb574b926b73dd2efba2a2b9d2d730517e8f7622/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", size = 265934 },
{ url = "https://files.pythonhosted.org/packages/d5/c9/3075eb7f7f3a91f1a6b00284af4de0a65a9ae47084930916f5528144c9dd/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", size = 283859 },
{ url = "https://files.pythonhosted.org/packages/05/f5/549f44d314c29408b962fa2b0e69a1a67c59379fb143b92a0a065ffd1f0f/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", size = 287560 },
{ url = "https://files.pythonhosted.org/packages/9d/f8/cb09b3c24a3eac02c4c07a9558e11e9e244fb02bf62c85ac2106d1eb0c0b/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", size = 277150 },
{ url = "https://files.pythonhosted.org/packages/37/48/38c2db3f54d1501e692d6fe058f45b6ad1b358d82cd19436efab80cfc965/frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", size = 45244 },
{ url = "https://files.pythonhosted.org/packages/ca/8c/2ddffeb8b60a4bce3b196c32fcc30d8830d4615e7b492ec2071da801b8ad/frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", size = 51634 },
{ url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 },
{ url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 },
{ url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 },
{ url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 },
{ url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 },
{ url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 },
{ url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 },
{ url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 },
{ url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 },
{ url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 },
{ url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 },
{ url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 },
{ url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 },
{ url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 },
{ url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 },
{ url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 },
{ url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 },
{ url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 },
{ url = "https://files.pythonhosted.org/packages/1f/22/462a3dd093d11df623179d7754a3b3269de3b42de2808cddef50ee0f4f48/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", size = 265636 },
{ url = "https://files.pythonhosted.org/packages/80/cf/e075e407fc2ae7328155a1cd7e22f932773c8073c1fc78016607d19cc3e5/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", size = 270214 },
{ url = "https://files.pythonhosted.org/packages/a1/58/0642d061d5de779f39c50cbb00df49682832923f3d2ebfb0fedf02d05f7f/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", size = 273905 },
{ url = "https://files.pythonhosted.org/packages/ab/66/3fe0f5f8f2add5b4ab7aa4e199f767fd3b55da26e3ca4ce2cc36698e50c4/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", size = 250542 },
{ url = "https://files.pythonhosted.org/packages/f6/b8/260791bde9198c87a465224e0e2bb62c4e716f5d198fc3a1dacc4895dbd1/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", size = 267026 },
{ url = "https://files.pythonhosted.org/packages/2e/a4/3d24f88c527f08f8d44ade24eaee83b2627793fa62fa07cbb7ff7a2f7d42/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", size = 257690 },
{ url = "https://files.pythonhosted.org/packages/de/9a/d311d660420b2beeff3459b6626f2ab4fb236d07afbdac034a4371fe696e/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", size = 253893 },
{ url = "https://files.pythonhosted.org/packages/c6/23/e491aadc25b56eabd0f18c53bb19f3cdc6de30b2129ee0bc39cd387cd560/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", size = 267006 },
{ url = "https://files.pythonhosted.org/packages/08/c4/ab918ce636a35fb974d13d666dcbe03969592aeca6c3ab3835acff01f79c/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", size = 276157 },
{ url = "https://files.pythonhosted.org/packages/c0/29/3b7a0bbbbe5a34833ba26f686aabfe982924adbdcafdc294a7a129c31688/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", size = 264642 },
{ url = "https://files.pythonhosted.org/packages/ab/42/0595b3dbffc2e82d7fe658c12d5a5bafcd7516c6bf2d1d1feb5387caa9c1/frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", size = 44914 },
{ url = "https://files.pythonhosted.org/packages/17/c4/b7db1206a3fea44bf3b838ca61deb6f74424a8a5db1dd53ecb21da669be6/frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", size = 51167 },
{ url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 },
]
[[package]]
name = "fsspec"
version = "2024.12.0"
@@ -719,17 +865,18 @@ wheels = [
[[package]]
name = "httpx"
version = "0.28.1"
version = "0.27.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "certifi" },
{ name = "httpcore" },
{ name = "idna" },
{ name = "sniffio" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 }
sdist = { url = "https://files.pythonhosted.org/packages/78/82/08f8c936781f67d9e6b9eeb8a0c8b4e406136ea4c3d1f89a5db71d42e0e6/httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2", size = 144189 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
{ url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395 },
]
[package.optional-dependencies]
@@ -806,6 +953,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461 },
]
[[package]]
name = "jinja2"
version = "3.1.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markupsafe" },
]
sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 },
]
[[package]]
name = "jiter"
version = "0.8.2"
@@ -853,6 +1012,33 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/91/61/c80ef80ed8a0a21158e289ef70dac01e351d929a1c30cb0f49be60772547/jiter-0.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566", size = 202374 },
]
[[package]]
name = "jsonschema"
version = "4.23.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "jsonschema-specifications" },
{ name = "referencing" },
{ name = "rpds-py" },
]
sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 },
]
[[package]]
name = "jsonschema-specifications"
version = "2024.10.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "referencing" },
]
sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 },
]
[[package]]
name = "kubernetes"
version = "31.0.0"
@@ -875,6 +1061,28 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/fb/a8/17f5e28cecdbd6d48127c22abdb794740803491f422a11905c4569d8e139/kubernetes-31.0.0-py2.py3-none-any.whl", hash = "sha256:bf141e2d380c8520eada8b351f4e319ffee9636328c137aa432bc486ca1200e1", size = 1857013 },
]
[[package]]
name = "litellm"
version = "1.59.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohttp" },
{ name = "click" },
{ name = "httpx" },
{ name = "importlib-metadata" },
{ name = "jinja2" },
{ name = "jsonschema" },
{ name = "openai" },
{ name = "pydantic" },
{ name = "python-dotenv" },
{ name = "tiktoken" },
{ name = "tokenizers" },
]
sdist = { url = "https://files.pythonhosted.org/packages/92/98/80766e2820e140b4b03a4b3e997d25e522bc2ce1d3c79c98a7b856a84e1f/litellm-1.59.1.tar.gz", hash = "sha256:ca4fd7789cc493daa63fe0dd69e3351237708c48a9305ccbc685a1bcf9eecf98", size = 6374267 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ff/3c/d2edad7c3cc85d83a4a6929c80ee258ae8875e2366366b9ab93eaf817cb3/litellm-1.59.1-py3-none-any.whl", hash = "sha256:69adf83f6942b9b62d3398cd8c1dc2e53b02e9b97bc5c45c427ed917629048e7", size = 6661803 },
]
[[package]]
name = "lxml"
version = "5.3.0"
@@ -998,6 +1206,54 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8f/f1/b67a849dfbe3bc95fea6b7ba60ed47dbf5b5442131345e4c4f5d48c6216e/markitdown-0.0.1a3-py3-none-any.whl", hash = "sha256:6efcab2f05714675486dc2ddf912415734b1caa0343f73f75d852046f04e5f37", size = 16199 },
]
[[package]]
name = "markupsafe"
version = "3.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 },
{ url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 },
{ url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 },
{ url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 },
{ url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 },
{ url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 },
{ url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 },
{ url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 },
{ url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 },
{ url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 },
{ url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 },
{ url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 },
{ url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 },
{ url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 },
{ url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 },
{ url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 },
{ url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 },
{ url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 },
{ url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 },
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 },
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 },
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 },
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 },
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 },
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 },
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 },
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 },
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 },
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 },
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 },
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 },
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 },
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 },
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 },
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 },
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 },
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 },
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 },
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 },
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
]
[[package]]
name = "mdurl"
version = "0.1.2"
@@ -1098,6 +1354,60 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 },
]
[[package]]
name = "multidict"
version = "6.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/93/13/df3505a46d0cd08428e4c8169a196131d1b0c4b515c3649829258843dde6/multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", size = 48570 },
{ url = "https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", size = 29316 },
{ url = "https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", size = 29640 },
{ url = "https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", size = 131067 },
{ url = "https://files.pythonhosted.org/packages/cc/1e/1b34154fef373371fd6c65125b3d42ff5f56c7ccc6bfff91b9b3c60ae9e0/multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", size = 138507 },
{ url = "https://files.pythonhosted.org/packages/fb/e0/0bc6b2bac6e461822b5f575eae85da6aae76d0e2a79b6665d6206b8e2e48/multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", size = 133905 },
{ url = "https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", size = 129004 },
{ url = "https://files.pythonhosted.org/packages/74/21/23960627b00ed39643302d81bcda44c9444ebcdc04ee5bedd0757513f259/multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", size = 121308 },
{ url = "https://files.pythonhosted.org/packages/8b/5c/cf282263ffce4a596ed0bb2aa1a1dddfe1996d6a62d08842a8d4b33dca13/multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", size = 132608 },
{ url = "https://files.pythonhosted.org/packages/d7/3e/97e778c041c72063f42b290888daff008d3ab1427f5b09b714f5a8eff294/multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", size = 127029 },
{ url = "https://files.pythonhosted.org/packages/47/ac/3efb7bfe2f3aefcf8d103e9a7162572f01936155ab2f7ebcc7c255a23212/multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", size = 137594 },
{ url = "https://files.pythonhosted.org/packages/42/9b/6c6e9e8dc4f915fc90a9b7798c44a30773dea2995fdcb619870e705afe2b/multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", size = 134556 },
{ url = "https://files.pythonhosted.org/packages/1d/10/8e881743b26aaf718379a14ac58572a240e8293a1c9d68e1418fb11c0f90/multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", size = 130993 },
{ url = "https://files.pythonhosted.org/packages/45/84/3eb91b4b557442802d058a7579e864b329968c8d0ea57d907e7023c677f2/multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", size = 26405 },
{ url = "https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", size = 28795 },
{ url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 },
{ url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 },
{ url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 },
{ url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 },
{ url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 },
{ url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 },
{ url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 },
{ url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 },
{ url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 },
{ url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 },
{ url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 },
{ url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 },
{ url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 },
{ url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 },
{ url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 },
{ url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 },
{ url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 },
{ url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 },
{ url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 },
{ url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 },
{ url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 },
{ url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 },
{ url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 },
{ url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 },
{ url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 },
{ url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 },
{ url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 },
{ url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 },
{ url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 },
{ url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 },
{ url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 },
]
[[package]]
name = "numpy"
version = "2.2.1"
@@ -1558,7 +1868,7 @@ wheels = [
[[package]]
name = "praisonaiagents"
version = "0.0.39"
version = "0.0.50"
source = { editable = "." }
dependencies = [
{ name = "openai" },
@@ -1570,8 +1880,10 @@ dependencies = [
all = [
{ name = "chonkie" },
{ name = "chromadb" },
{ name = "litellm" },
{ name = "markitdown" },
{ name = "mem0ai" },
{ name = "pydantic" },
]
knowledge = [
{ name = "chonkie" },
@@ -1579,6 +1891,10 @@ knowledge = [
{ name = "markitdown" },
{ name = "mem0ai" },
]
llm = [
{ name = "litellm" },
{ name = "pydantic" },
]
memory = [
{ name = "chromadb" },
]
@@ -1588,15 +1904,75 @@ requires-dist = [
{ name = "chonkie", marker = "extra == 'knowledge'" },
{ name = "chromadb", marker = "extra == 'knowledge'", specifier = "==0.5.23" },
{ name = "chromadb", marker = "extra == 'memory'", specifier = ">=0.5.23" },
{ name = "litellm", marker = "extra == 'llm'", specifier = ">=1.50.0" },
{ name = "markitdown", marker = "extra == 'knowledge'" },
{ name = "mem0ai", marker = "extra == 'knowledge'", specifier = ">=0.1.0" },
{ name = "openai" },
{ name = "praisonaiagents", extras = ["knowledge"], marker = "extra == 'all'" },
{ name = "praisonaiagents", extras = ["llm"], marker = "extra == 'all'" },
{ name = "praisonaiagents", extras = ["memory"], marker = "extra == 'all'" },
{ name = "pydantic" },
{ name = "pydantic", marker = "extra == 'llm'", specifier = ">=2.4.2" },
{ name = "rich" },
]
[[package]]
name = "propcache"
version = "0.2.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/20/c8/2a13f78d82211490855b2fb303b6721348d0787fdd9a12ac46d99d3acde1/propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64", size = 41735 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bc/0f/2913b6791ebefb2b25b4efd4bb2299c985e09786b9f5b19184a88e5778dd/propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16", size = 79297 },
{ url = "https://files.pythonhosted.org/packages/cf/73/af2053aeccd40b05d6e19058419ac77674daecdd32478088b79375b9ab54/propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717", size = 45611 },
{ url = "https://files.pythonhosted.org/packages/3c/09/8386115ba7775ea3b9537730e8cf718d83bbf95bffe30757ccf37ec4e5da/propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3", size = 45146 },
{ url = "https://files.pythonhosted.org/packages/03/7a/793aa12f0537b2e520bf09f4c6833706b63170a211ad042ca71cbf79d9cb/propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9", size = 232136 },
{ url = "https://files.pythonhosted.org/packages/f1/38/b921b3168d72111769f648314100558c2ea1d52eb3d1ba7ea5c4aa6f9848/propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787", size = 239706 },
{ url = "https://files.pythonhosted.org/packages/14/29/4636f500c69b5edea7786db3c34eb6166f3384b905665ce312a6e42c720c/propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465", size = 238531 },
{ url = "https://files.pythonhosted.org/packages/85/14/01fe53580a8e1734ebb704a3482b7829a0ef4ea68d356141cf0994d9659b/propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af", size = 231063 },
{ url = "https://files.pythonhosted.org/packages/33/5c/1d961299f3c3b8438301ccfbff0143b69afcc30c05fa28673cface692305/propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7", size = 220134 },
{ url = "https://files.pythonhosted.org/packages/00/d0/ed735e76db279ba67a7d3b45ba4c654e7b02bc2f8050671ec365d8665e21/propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f", size = 220009 },
{ url = "https://files.pythonhosted.org/packages/75/90/ee8fab7304ad6533872fee982cfff5a53b63d095d78140827d93de22e2d4/propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54", size = 212199 },
{ url = "https://files.pythonhosted.org/packages/eb/ec/977ffaf1664f82e90737275873461695d4c9407d52abc2f3c3e24716da13/propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505", size = 214827 },
{ url = "https://files.pythonhosted.org/packages/57/48/031fb87ab6081764054821a71b71942161619549396224cbb242922525e8/propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82", size = 228009 },
{ url = "https://files.pythonhosted.org/packages/1a/06/ef1390f2524850838f2390421b23a8b298f6ce3396a7cc6d39dedd4047b0/propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca", size = 231638 },
{ url = "https://files.pythonhosted.org/packages/38/2a/101e6386d5a93358395da1d41642b79c1ee0f3b12e31727932b069282b1d/propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e", size = 222788 },
{ url = "https://files.pythonhosted.org/packages/db/81/786f687951d0979007e05ad9346cd357e50e3d0b0f1a1d6074df334b1bbb/propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034", size = 40170 },
{ url = "https://files.pythonhosted.org/packages/cf/59/7cc7037b295d5772eceb426358bb1b86e6cab4616d971bd74275395d100d/propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3", size = 44404 },
{ url = "https://files.pythonhosted.org/packages/4c/28/1d205fe49be8b1b4df4c50024e62480a442b1a7b818e734308bb0d17e7fb/propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a", size = 79588 },
{ url = "https://files.pythonhosted.org/packages/21/ee/fc4d893f8d81cd4971affef2a6cb542b36617cd1d8ce56b406112cb80bf7/propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0", size = 45825 },
{ url = "https://files.pythonhosted.org/packages/4a/de/bbe712f94d088da1d237c35d735f675e494a816fd6f54e9db2f61ef4d03f/propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d", size = 45357 },
{ url = "https://files.pythonhosted.org/packages/7f/14/7ae06a6cf2a2f1cb382586d5a99efe66b0b3d0c6f9ac2f759e6f7af9d7cf/propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4", size = 241869 },
{ url = "https://files.pythonhosted.org/packages/cc/59/227a78be960b54a41124e639e2c39e8807ac0c751c735a900e21315f8c2b/propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d", size = 247884 },
{ url = "https://files.pythonhosted.org/packages/84/58/f62b4ffaedf88dc1b17f04d57d8536601e4e030feb26617228ef930c3279/propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5", size = 248486 },
{ url = "https://files.pythonhosted.org/packages/1c/07/ebe102777a830bca91bbb93e3479cd34c2ca5d0361b83be9dbd93104865e/propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24", size = 243649 },
{ url = "https://files.pythonhosted.org/packages/ed/bc/4f7aba7f08f520376c4bb6a20b9a981a581b7f2e385fa0ec9f789bb2d362/propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff", size = 229103 },
{ url = "https://files.pythonhosted.org/packages/fe/d5/04ac9cd4e51a57a96f78795e03c5a0ddb8f23ec098b86f92de028d7f2a6b/propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f", size = 226607 },
{ url = "https://files.pythonhosted.org/packages/e3/f0/24060d959ea41d7a7cc7fdbf68b31852331aabda914a0c63bdb0e22e96d6/propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec", size = 221153 },
{ url = "https://files.pythonhosted.org/packages/77/a7/3ac76045a077b3e4de4859a0753010765e45749bdf53bd02bc4d372da1a0/propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348", size = 222151 },
{ url = "https://files.pythonhosted.org/packages/e7/af/5e29da6f80cebab3f5a4dcd2a3240e7f56f2c4abf51cbfcc99be34e17f0b/propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6", size = 233812 },
{ url = "https://files.pythonhosted.org/packages/8c/89/ebe3ad52642cc5509eaa453e9f4b94b374d81bae3265c59d5c2d98efa1b4/propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6", size = 238829 },
{ url = "https://files.pythonhosted.org/packages/e9/2f/6b32f273fa02e978b7577159eae7471b3cfb88b48563b1c2578b2d7ca0bb/propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518", size = 230704 },
{ url = "https://files.pythonhosted.org/packages/5c/2e/f40ae6ff5624a5f77edd7b8359b208b5455ea113f68309e2b00a2e1426b6/propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246", size = 40050 },
{ url = "https://files.pythonhosted.org/packages/3b/77/a92c3ef994e47180862b9d7d11e37624fb1c00a16d61faf55115d970628b/propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1", size = 44117 },
{ url = "https://files.pythonhosted.org/packages/0f/2a/329e0547cf2def8857157f9477669043e75524cc3e6251cef332b3ff256f/propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc", size = 77002 },
{ url = "https://files.pythonhosted.org/packages/12/2d/c4df5415e2382f840dc2ecbca0eeb2293024bc28e57a80392f2012b4708c/propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9", size = 44639 },
{ url = "https://files.pythonhosted.org/packages/d0/5a/21aaa4ea2f326edaa4e240959ac8b8386ea31dedfdaa636a3544d9e7a408/propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439", size = 44049 },
{ url = "https://files.pythonhosted.org/packages/4e/3e/021b6cd86c0acc90d74784ccbb66808b0bd36067a1bf3e2deb0f3845f618/propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536", size = 224819 },
{ url = "https://files.pythonhosted.org/packages/3c/57/c2fdeed1b3b8918b1770a133ba5c43ad3d78e18285b0c06364861ef5cc38/propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629", size = 229625 },
{ url = "https://files.pythonhosted.org/packages/9d/81/70d4ff57bf2877b5780b466471bebf5892f851a7e2ca0ae7ffd728220281/propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b", size = 232934 },
{ url = "https://files.pythonhosted.org/packages/3c/b9/bb51ea95d73b3fb4100cb95adbd4e1acaf2cbb1fd1083f5468eeb4a099a8/propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052", size = 227361 },
{ url = "https://files.pythonhosted.org/packages/f1/20/3c6d696cd6fd70b29445960cc803b1851a1131e7a2e4ee261ee48e002bcd/propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce", size = 213904 },
{ url = "https://files.pythonhosted.org/packages/a1/cb/1593bfc5ac6d40c010fa823f128056d6bc25b667f5393781e37d62f12005/propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d", size = 212632 },
{ url = "https://files.pythonhosted.org/packages/6d/5c/e95617e222be14a34c709442a0ec179f3207f8a2b900273720501a70ec5e/propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce", size = 207897 },
{ url = "https://files.pythonhosted.org/packages/8e/3b/56c5ab3dc00f6375fbcdeefdede5adf9bee94f1fab04adc8db118f0f9e25/propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95", size = 208118 },
{ url = "https://files.pythonhosted.org/packages/86/25/d7ef738323fbc6ebcbce33eb2a19c5e07a89a3df2fded206065bd5e868a9/propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf", size = 217851 },
{ url = "https://files.pythonhosted.org/packages/b3/77/763e6cef1852cf1ba740590364ec50309b89d1c818e3256d3929eb92fabf/propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f", size = 222630 },
{ url = "https://files.pythonhosted.org/packages/4f/e9/0f86be33602089c701696fbed8d8c4c07b6ee9605c5b7536fd27ed540c5b/propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30", size = 216269 },
{ url = "https://files.pythonhosted.org/packages/cc/02/5ac83217d522394b6a2e81a2e888167e7ca629ef6569a3f09852d6dcb01a/propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6", size = 39472 },
{ url = "https://files.pythonhosted.org/packages/f4/33/d6f5420252a36034bc8a3a01171bc55b4bff5df50d1c63d9caa50693662f/propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1", size = 43363 },
{ url = "https://files.pythonhosted.org/packages/41/b6/c5319caea262f4821995dca2107483b94a3345d4607ad797c76cb9c36bcc/propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54", size = 11818 },
]
[[package]]
name = "protobuf"
version = "5.29.3"
@@ -1873,6 +2249,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/00/27c6eb6fc764e2b3d26ddeab4aedab855c050c906ec018bdd669b18f3157/qdrant_client-1.12.2-py3-none-any.whl", hash = "sha256:a0ae500a46a679ff3521ba3f1f1cf3d72b57090a768cec65fc317066bcbac1e6", size = 267173 },
]
[[package]]
name = "referencing"
version = "0.36.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "rpds-py" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/27/32/fd98246df7a0f309b58cae68b10b6b219ef2eb66747f00dfb34422687087/referencing-0.36.1.tar.gz", hash = "sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade", size = 74661 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/fa/9f193ef0c9074b659009f06d7cbacc6f25b072044815bcf799b76533dbb8/referencing-0.36.1-py3-none-any.whl", hash = "sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794", size = 26777 },
]
[[package]]
name = "regex"
version = "2024.11.6"
@@ -1967,6 +2357,66 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
]
[[package]]
name = "rpds-py"
version = "0.22.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/01/80/cce854d0921ff2f0a9fa831ba3ad3c65cee3a46711addf39a2af52df2cfd/rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d", size = 26771 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/15/ad/8d1ddf78f2805a71253fcd388017e7b4a0615c22c762b6d35301fef20106/rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f", size = 359773 },
{ url = "https://files.pythonhosted.org/packages/c8/75/68c15732293a8485d79fe4ebe9045525502a067865fa4278f178851b2d87/rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a", size = 349214 },
{ url = "https://files.pythonhosted.org/packages/3c/4c/7ce50f3070083c2e1b2bbd0fb7046f3da55f510d19e283222f8f33d7d5f4/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5", size = 380477 },
{ url = "https://files.pythonhosted.org/packages/9a/e9/835196a69cb229d5c31c13b8ae603bd2da9a6695f35fe4270d398e1db44c/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb", size = 386171 },
{ url = "https://files.pythonhosted.org/packages/f9/8e/33fc4eba6683db71e91e6d594a2cf3a8fbceb5316629f0477f7ece5e3f75/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2", size = 422676 },
{ url = "https://files.pythonhosted.org/packages/37/47/2e82d58f8046a98bb9497a8319604c92b827b94d558df30877c4b3c6ccb3/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0", size = 446152 },
{ url = "https://files.pythonhosted.org/packages/e1/78/79c128c3e71abbc8e9739ac27af11dc0f91840a86fce67ff83c65d1ba195/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1", size = 381300 },
{ url = "https://files.pythonhosted.org/packages/c9/5b/2e193be0e8b228c1207f31fa3ea79de64dadb4f6a4833111af8145a6bc33/rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d", size = 409636 },
{ url = "https://files.pythonhosted.org/packages/c2/3f/687c7100b762d62186a1c1100ffdf99825f6fa5ea94556844bbbd2d0f3a9/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648", size = 556708 },
{ url = "https://files.pythonhosted.org/packages/8c/a2/c00cbc4b857e8b3d5e7f7fc4c81e23afd8c138b930f4f3ccf9a41a23e9e4/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74", size = 583554 },
{ url = "https://files.pythonhosted.org/packages/d0/08/696c9872cf56effdad9ed617ac072f6774a898d46b8b8964eab39ec562d2/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a", size = 552105 },
{ url = "https://files.pythonhosted.org/packages/18/1f/4df560be1e994f5adf56cabd6c117e02de7c88ee238bb4ce03ed50da9d56/rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64", size = 220199 },
{ url = "https://files.pythonhosted.org/packages/b8/1b/c29b570bc5db8237553002788dc734d6bd71443a2ceac2a58202ec06ef12/rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c", size = 231775 },
{ url = "https://files.pythonhosted.org/packages/75/47/3383ee3bd787a2a5e65a9b9edc37ccf8505c0a00170e3a5e6ea5fbcd97f7/rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e", size = 352334 },
{ url = "https://files.pythonhosted.org/packages/40/14/aa6400fa8158b90a5a250a77f2077c0d0cd8a76fce31d9f2b289f04c6dec/rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56", size = 342111 },
{ url = "https://files.pythonhosted.org/packages/7d/06/395a13bfaa8a28b302fb433fb285a67ce0ea2004959a027aea8f9c52bad4/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45", size = 384286 },
{ url = "https://files.pythonhosted.org/packages/43/52/d8eeaffab047e6b7b7ef7f00d5ead074a07973968ffa2d5820fa131d7852/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e", size = 391739 },
{ url = "https://files.pythonhosted.org/packages/83/31/52dc4bde85c60b63719610ed6f6d61877effdb5113a72007679b786377b8/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d", size = 427306 },
{ url = "https://files.pythonhosted.org/packages/70/d5/1bab8e389c2261dba1764e9e793ed6830a63f830fdbec581a242c7c46bda/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38", size = 442717 },
{ url = "https://files.pythonhosted.org/packages/82/a1/a45f3e30835b553379b3a56ea6c4eb622cf11e72008229af840e4596a8ea/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15", size = 385721 },
{ url = "https://files.pythonhosted.org/packages/a6/27/780c942de3120bdd4d0e69583f9c96e179dfff082f6ecbb46b8d6488841f/rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059", size = 415824 },
{ url = "https://files.pythonhosted.org/packages/94/0b/aa0542ca88ad20ea719b06520f925bae348ea5c1fdf201b7e7202d20871d/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e", size = 561227 },
{ url = "https://files.pythonhosted.org/packages/0d/92/3ed77d215f82c8f844d7f98929d56cc321bb0bcfaf8f166559b8ec56e5f1/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61", size = 587424 },
{ url = "https://files.pythonhosted.org/packages/09/42/cacaeb047a22cab6241f107644f230e2935d4efecf6488859a7dd82fc47d/rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7", size = 555953 },
{ url = "https://files.pythonhosted.org/packages/e6/52/c921dc6d5f5d45b212a456c1f5b17df1a471127e8037eb0972379e39dff4/rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627", size = 221339 },
{ url = "https://files.pythonhosted.org/packages/f2/c7/f82b5be1e8456600395366f86104d1bd8d0faed3802ad511ef6d60c30d98/rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4", size = 235786 },
{ url = "https://files.pythonhosted.org/packages/d0/bf/36d5cc1f2c609ae6e8bf0fc35949355ca9d8790eceb66e6385680c951e60/rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84", size = 351657 },
{ url = "https://files.pythonhosted.org/packages/24/2a/f1e0fa124e300c26ea9382e59b2d582cba71cedd340f32d1447f4f29fa4e/rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25", size = 341829 },
{ url = "https://files.pythonhosted.org/packages/cf/c2/0da1231dd16953845bed60d1a586fcd6b15ceaeb965f4d35cdc71f70f606/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4", size = 384220 },
{ url = "https://files.pythonhosted.org/packages/c7/73/a4407f4e3a00a9d4b68c532bf2d873d6b562854a8eaff8faa6133b3588ec/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5", size = 391009 },
{ url = "https://files.pythonhosted.org/packages/a9/c3/04b7353477ab360fe2563f5f0b176d2105982f97cd9ae80a9c5a18f1ae0f/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc", size = 426989 },
{ url = "https://files.pythonhosted.org/packages/8d/e6/e4b85b722bcf11398e17d59c0f6049d19cd606d35363221951e6d625fcb0/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b", size = 441544 },
{ url = "https://files.pythonhosted.org/packages/27/fc/403e65e56f65fff25f2973216974976d3f0a5c3f30e53758589b6dc9b79b/rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518", size = 385179 },
{ url = "https://files.pythonhosted.org/packages/57/9b/2be9ff9700d664d51fd96b33d6595791c496d2778cb0b2a634f048437a55/rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd", size = 415103 },
{ url = "https://files.pythonhosted.org/packages/bb/a5/03c2ad8ca10994fcf22dd2150dd1d653bc974fa82d9a590494c84c10c641/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2", size = 560916 },
{ url = "https://files.pythonhosted.org/packages/ba/2e/be4fdfc8b5b576e588782b56978c5b702c5a2307024120d8aeec1ab818f0/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16", size = 587062 },
{ url = "https://files.pythonhosted.org/packages/67/e0/2034c221937709bf9c542603d25ad43a68b4b0a9a0c0b06a742f2756eb66/rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f", size = 555734 },
{ url = "https://files.pythonhosted.org/packages/ea/ce/240bae07b5401a22482b58e18cfbabaa392409b2797da60223cca10d7367/rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de", size = 220663 },
{ url = "https://files.pythonhosted.org/packages/cb/f0/d330d08f51126330467edae2fa4efa5cec8923c87551a79299380fdea30d/rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9", size = 235503 },
{ url = "https://files.pythonhosted.org/packages/f7/c4/dbe1cc03df013bf2feb5ad00615038050e7859f381e96fb5b7b4572cd814/rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b", size = 347698 },
{ url = "https://files.pythonhosted.org/packages/a4/3a/684f66dd6b0f37499cad24cd1c0e523541fd768576fa5ce2d0a8799c3cba/rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b", size = 337330 },
{ url = "https://files.pythonhosted.org/packages/82/eb/e022c08c2ce2e8f7683baa313476492c0e2c1ca97227fe8a75d9f0181e95/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1", size = 380022 },
{ url = "https://files.pythonhosted.org/packages/e4/21/5a80e653e4c86aeb28eb4fea4add1f72e1787a3299687a9187105c3ee966/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83", size = 390754 },
{ url = "https://files.pythonhosted.org/packages/37/a4/d320a04ae90f72d080b3d74597074e62be0a8ecad7d7321312dfe2dc5a6a/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd", size = 423840 },
{ url = "https://files.pythonhosted.org/packages/87/70/674dc47d93db30a6624279284e5631be4c3a12a0340e8e4f349153546728/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1", size = 438970 },
{ url = "https://files.pythonhosted.org/packages/3f/64/9500f4d66601d55cadd21e90784cfd5d5f4560e129d72e4339823129171c/rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3", size = 383146 },
{ url = "https://files.pythonhosted.org/packages/4d/45/630327addb1d17173adcf4af01336fd0ee030c04798027dfcb50106001e0/rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130", size = 408294 },
{ url = "https://files.pythonhosted.org/packages/5f/ef/8efb3373cee54ea9d9980b772e5690a0c9e9214045a4e7fa35046e399fee/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c", size = 556345 },
{ url = "https://files.pythonhosted.org/packages/54/01/151d3b9ef4925fc8f15bfb131086c12ec3c3d6dd4a4f7589c335bf8e85ba/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b", size = 582292 },
{ url = "https://files.pythonhosted.org/packages/30/89/35fc7a6cdf3477d441c7aca5e9bbf5a14e0f25152aed7f63f4e0b141045d/rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333", size = 553855 },
{ url = "https://files.pythonhosted.org/packages/8f/e0/830c02b2457c4bd20a8c5bb394d31d81f57fbefce2dbdd2e31feff4f7003/rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730", size = 219100 },
{ url = "https://files.pythonhosted.org/packages/f8/30/7ac943f69855c2db77407ae363484b915d861702dbba1aa82d68d57f42be/rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf", size = 233794 },
]
[[package]]
name = "rsa"
version = "4.9"
@@ -2465,6 +2915,68 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/ea/53d1fe468e63e092cf16e2c18d16f50c29851242f9dd12d6a66e0d7f0d02/XlsxWriter-3.2.0-py3-none-any.whl", hash = "sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e", size = 159925 },
]
[[package]]
name = "yarl"
version = "1.18.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "idna" },
{ name = "multidict" },
{ name = "propcache" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b7/9d/4b94a8e6d2b51b599516a5cb88e5bc99b4d8d4583e468057eaa29d5f0918/yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", size = 181062 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/40/93/282b5f4898d8e8efaf0790ba6d10e2245d2c9f30e199d1a85cae9356098c/yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069", size = 141555 },
{ url = "https://files.pythonhosted.org/packages/6d/9c/0a49af78df099c283ca3444560f10718fadb8a18dc8b3edf8c7bd9fd7d89/yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193", size = 94351 },
{ url = "https://files.pythonhosted.org/packages/5a/a1/205ab51e148fdcedad189ca8dd587794c6f119882437d04c33c01a75dece/yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889", size = 92286 },
{ url = "https://files.pythonhosted.org/packages/ed/fe/88b690b30f3f59275fb674f5f93ddd4a3ae796c2b62e5bb9ece8a4914b83/yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8", size = 340649 },
{ url = "https://files.pythonhosted.org/packages/07/eb/3b65499b568e01f36e847cebdc8d7ccb51fff716dbda1ae83c3cbb8ca1c9/yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca", size = 356623 },
{ url = "https://files.pythonhosted.org/packages/33/46/f559dc184280b745fc76ec6b1954de2c55595f0ec0a7614238b9ebf69618/yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8", size = 354007 },
{ url = "https://files.pythonhosted.org/packages/af/ba/1865d85212351ad160f19fb99808acf23aab9a0f8ff31c8c9f1b4d671fc9/yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae", size = 344145 },
{ url = "https://files.pythonhosted.org/packages/94/cb/5c3e975d77755d7b3d5193e92056b19d83752ea2da7ab394e22260a7b824/yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3", size = 336133 },
{ url = "https://files.pythonhosted.org/packages/19/89/b77d3fd249ab52a5c40859815765d35c91425b6bb82e7427ab2f78f5ff55/yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb", size = 347967 },
{ url = "https://files.pythonhosted.org/packages/35/bd/f6b7630ba2cc06c319c3235634c582a6ab014d52311e7d7c22f9518189b5/yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e", size = 346397 },
{ url = "https://files.pythonhosted.org/packages/18/1a/0b4e367d5a72d1f095318344848e93ea70da728118221f84f1bf6c1e39e7/yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59", size = 350206 },
{ url = "https://files.pythonhosted.org/packages/b5/cf/320fff4367341fb77809a2d8d7fe75b5d323a8e1b35710aafe41fdbf327b/yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d", size = 362089 },
{ url = "https://files.pythonhosted.org/packages/57/cf/aadba261d8b920253204085268bad5e8cdd86b50162fcb1b10c10834885a/yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e", size = 366267 },
{ url = "https://files.pythonhosted.org/packages/54/58/fb4cadd81acdee6dafe14abeb258f876e4dd410518099ae9a35c88d8097c/yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a", size = 359141 },
{ url = "https://files.pythonhosted.org/packages/9a/7a/4c571597589da4cd5c14ed2a0b17ac56ec9ee7ee615013f74653169e702d/yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1", size = 84402 },
{ url = "https://files.pythonhosted.org/packages/ae/7b/8600250b3d89b625f1121d897062f629883c2f45339623b69b1747ec65fa/yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5", size = 91030 },
{ url = "https://files.pythonhosted.org/packages/33/85/bd2e2729752ff4c77338e0102914897512e92496375e079ce0150a6dc306/yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", size = 142644 },
{ url = "https://files.pythonhosted.org/packages/ff/74/1178322cc0f10288d7eefa6e4a85d8d2e28187ccab13d5b844e8b5d7c88d/yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", size = 94962 },
{ url = "https://files.pythonhosted.org/packages/be/75/79c6acc0261e2c2ae8a1c41cf12265e91628c8c58ae91f5ff59e29c0787f/yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", size = 92795 },
{ url = "https://files.pythonhosted.org/packages/6b/32/927b2d67a412c31199e83fefdce6e645247b4fb164aa1ecb35a0f9eb2058/yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", size = 332368 },
{ url = "https://files.pythonhosted.org/packages/19/e5/859fca07169d6eceeaa4fde1997c91d8abde4e9a7c018e371640c2da2b71/yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", size = 342314 },
{ url = "https://files.pythonhosted.org/packages/08/75/76b63ccd91c9e03ab213ef27ae6add2e3400e77e5cdddf8ed2dbc36e3f21/yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", size = 341987 },
{ url = "https://files.pythonhosted.org/packages/1a/e1/a097d5755d3ea8479a42856f51d97eeff7a3a7160593332d98f2709b3580/yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", size = 336914 },
{ url = "https://files.pythonhosted.org/packages/0b/42/e1b4d0e396b7987feceebe565286c27bc085bf07d61a59508cdaf2d45e63/yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", size = 325765 },
{ url = "https://files.pythonhosted.org/packages/7e/18/03a5834ccc9177f97ca1bbb245b93c13e58e8225276f01eedc4cc98ab820/yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", size = 344444 },
{ url = "https://files.pythonhosted.org/packages/c8/03/a713633bdde0640b0472aa197b5b86e90fbc4c5bc05b727b714cd8a40e6d/yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", size = 340760 },
{ url = "https://files.pythonhosted.org/packages/eb/99/f6567e3f3bbad8fd101886ea0276c68ecb86a2b58be0f64077396cd4b95e/yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", size = 346484 },
{ url = "https://files.pythonhosted.org/packages/8e/a9/84717c896b2fc6cb15bd4eecd64e34a2f0a9fd6669e69170c73a8b46795a/yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", size = 359864 },
{ url = "https://files.pythonhosted.org/packages/1e/2e/d0f5f1bef7ee93ed17e739ec8dbcb47794af891f7d165fa6014517b48169/yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", size = 364537 },
{ url = "https://files.pythonhosted.org/packages/97/8a/568d07c5d4964da5b02621a517532adb8ec5ba181ad1687191fffeda0ab6/yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", size = 357861 },
{ url = "https://files.pythonhosted.org/packages/7d/e3/924c3f64b6b3077889df9a1ece1ed8947e7b61b0a933f2ec93041990a677/yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", size = 84097 },
{ url = "https://files.pythonhosted.org/packages/34/45/0e055320daaabfc169b21ff6174567b2c910c45617b0d79c68d7ab349b02/yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", size = 90399 },
{ url = "https://files.pythonhosted.org/packages/30/c7/c790513d5328a8390be8f47be5d52e141f78b66c6c48f48d241ca6bd5265/yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", size = 140789 },
{ url = "https://files.pythonhosted.org/packages/30/aa/a2f84e93554a578463e2edaaf2300faa61c8701f0898725842c704ba5444/yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", size = 94144 },
{ url = "https://files.pythonhosted.org/packages/c6/fc/d68d8f83714b221a85ce7866832cba36d7c04a68fa6a960b908c2c84f325/yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", size = 91974 },
{ url = "https://files.pythonhosted.org/packages/56/4e/d2563d8323a7e9a414b5b25341b3942af5902a2263d36d20fb17c40411e2/yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", size = 333587 },
{ url = "https://files.pythonhosted.org/packages/25/c9/cfec0bc0cac8d054be223e9f2c7909d3e8442a856af9dbce7e3442a8ec8d/yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", size = 344386 },
{ url = "https://files.pythonhosted.org/packages/ab/5d/4c532190113b25f1364d25f4c319322e86232d69175b91f27e3ebc2caf9a/yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", size = 345421 },
{ url = "https://files.pythonhosted.org/packages/23/d1/6cdd1632da013aa6ba18cee4d750d953104a5e7aac44e249d9410a972bf5/yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", size = 339384 },
{ url = "https://files.pythonhosted.org/packages/9a/c4/6b3c39bec352e441bd30f432cda6ba51681ab19bb8abe023f0d19777aad1/yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", size = 326689 },
{ url = "https://files.pythonhosted.org/packages/23/30/07fb088f2eefdc0aa4fc1af4e3ca4eb1a3aadd1ce7d866d74c0f124e6a85/yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", size = 345453 },
{ url = "https://files.pythonhosted.org/packages/63/09/d54befb48f9cd8eec43797f624ec37783a0266855f4930a91e3d5c7717f8/yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", size = 341872 },
{ url = "https://files.pythonhosted.org/packages/91/26/fd0ef9bf29dd906a84b59f0cd1281e65b0c3e08c6aa94b57f7d11f593518/yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", size = 347497 },
{ url = "https://files.pythonhosted.org/packages/d9/b5/14ac7a256d0511b2ac168d50d4b7d744aea1c1aa20c79f620d1059aab8b2/yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", size = 359981 },
{ url = "https://files.pythonhosted.org/packages/ca/b3/d493221ad5cbd18bc07e642894030437e405e1413c4236dd5db6e46bcec9/yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", size = 366229 },
{ url = "https://files.pythonhosted.org/packages/04/56/6a3e2a5d9152c56c346df9b8fb8edd2c8888b1e03f96324d457e5cf06d34/yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", size = 360383 },
{ url = "https://files.pythonhosted.org/packages/fd/b7/4b3c7c7913a278d445cc6284e59b2e62fa25e72758f888b7a7a39eb8423f/yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", size = 310152 },
{ url = "https://files.pythonhosted.org/packages/f5/d5/688db678e987c3e0fb17867970700b92603cadf36c56e5fb08f23e822a0c/yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", size = 315723 },
{ url = "https://files.pythonhosted.org/packages/f5/4b/a06e0ec3d155924f77835ed2d167ebd3b211a7b0853da1cf8d8414d784ef/yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", size = 45109 },
]
[[package]]
name = "youtube-transcript-api"
version = "0.6.3"
+39
View File
@@ -0,0 +1,39 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Define the configuration for the Knowledge instance
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
}
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="gpt-4o-mini"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
+1 -1
View File
@@ -1,6 +1,6 @@
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install flask praisonai==2.0.48 gunicorn markdown
RUN pip install flask praisonai==2.0.57 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.
+39
View File
@@ -6,6 +6,45 @@ icon: "robot"
PraisonAI provides a diverse set of specialized agents for various tasks. Each agent is designed with specific capabilities and tools to handle different types of tasks effectively.
```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
```
## Data & Analysis
<CardGroup cols={2}>
+1 -1
View File
@@ -110,7 +110,7 @@ Loads environment variables from .env file or system and sets them.</p>
file.write(&#34;FROM python:3.11-slim\n&#34;)
file.write(&#34;WORKDIR /app\n&#34;)
file.write(&#34;COPY . .\n&#34;)
file.write(&#34;RUN pip install flask praisonai==2.0.48 gunicorn markdown\n&#34;)
file.write(&#34;RUN pip install flask praisonai==2.0.57 gunicorn markdown\n&#34;)
file.write(&#34;EXPOSE 8080\n&#34;)
file.write(&#39;CMD [&#34;gunicorn&#34;, &#34;-b&#34;, &#34;0.0.0.0:8080&#34;, &#34;api:app&#34;]\n&#39;)
+1 -1
View File
@@ -14,7 +14,7 @@ flowchart LR
end
subgraph Router[Vector Store]
DB[(Chroma)]
DB[(Vector DB)]
end
subgraph Out[Agents]
+75
View File
@@ -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.
+297
View File
@@ -0,0 +1,297 @@
---
title: "Climate Impact"
description: "Learn how to create AI agents for climate impact analysis and adaptation strategies."
icon: "cloud-sun"
---
```mermaid
flowchart LR
In[In] --> Monitor[Environmental Monitor]
Monitor --> Urban[Urban Analyzer]
Urban --> Climate[Climate Modeler]
Climate --> Impact[Impact Predictor]
Impact --> Strategy[Strategy Generator]
Strategy --> Out[Out]
style In fill:#8B0000,color:#fff
style Monitor fill:#2E8B57,color:#fff
style Urban fill:#2E8B57,color:#fff
style Climate fill:#2E8B57,color:#fff
style Impact fill:#2E8B57,color:#fff
style Strategy fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Climate Impact Analysis?
Climate Impact Analysis is a systematic process of collecting environmental data, analyzing urban factors, modeling microclimates, predicting impacts, and generating adaptation strategies. This helps cities and communities understand and prepare for climate change effects, ensuring sustainable urban development and public health.
## Features
<CardGroup cols={2}>
<Card title="Environmental Monitoring" icon="temperature-high">
Collection of temperature, humidity, and air quality data with trend analysis.
</Card>
<Card title="Urban Analysis" icon="city">
Assessment of building density, green spaces, traffic flow, and heat islands.
</Card>
<Card title="Climate Modeling" icon="chart-line">
Microclimate modeling for different urban locations with temperature and air quality impacts.
</Card>
<Card title="Impact Prediction" icon="chart-mixed">
Prediction of health impacts, energy consumption, and livability scores.
</Card>
<Card title="Adaptation Strategies" icon="leaf">
Generation of location-specific strategies for climate adaptation.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def collect_environmental_data():
"""Simulates environmental data collection"""
data = {
"temperature": {
"current": 25 + (time.time() % 10),
"historical": [24, 25, 26, 24, 23],
"trend": "increasing"
},
"humidity": {
"current": 60 + (time.time() % 20),
"historical": [65, 62, 58, 63, 61],
"trend": "stable"
},
"air_quality": {
"pm25": 35 + (time.time() % 15),
"co2": 415 + (time.time() % 30),
"trend": "deteriorating"
}
}
return data
def analyze_urban_factors():
"""Simulates urban environment analysis"""
factors = {
"building_density": 75 + (time.time() % 20),
"green_spaces": 25 + (time.time() % 10),
"traffic_flow": {
"peak_hours": [8, 17],
"congestion_level": "high"
},
"heat_islands": [
{"location": "downtown", "intensity": "high"},
{"location": "industrial", "intensity": "medium"}
]
}
return factors
def model_microclimate(env_data: Dict, urban_factors: Dict):
"""Models microclimate conditions"""
models = []
locations = ["downtown", "residential", "industrial", "parks"]
for location in locations:
models.append({
"location": location,
"temperature_delta": 2 + (time.time() % 3),
"air_quality_impact": "moderate" if "park" in location else "significant",
"humidity_variation": 5 + (time.time() % 5)
})
return models
def predict_impacts(models: List[Dict]):
"""Predicts climate impacts"""
predictions = []
for model in models:
predictions.append({
"location": model["location"],
"health_impact": "high" if model["air_quality_impact"] == "significant" else "medium",
"energy_consumption": {
"cooling_need": model["temperature_delta"] * 10,
"trend": "increasing" if model["temperature_delta"] > 2.5 else "stable"
},
"livability_score": 70 - (model["temperature_delta"] * 5)
})
return predictions
def generate_adaptation_strategies(predictions: List[Dict]):
"""Generates adaptation strategies"""
strategies = []
for pred in predictions:
if pred["health_impact"] == "high":
strategies.append({
"location": pred["location"],
"actions": [
"increase_green_spaces",
"traffic_reduction",
"building_retrofitting"
],
"priority": "immediate",
"cost_estimate": "high"
})
else:
strategies.append({
"location": pred["location"],
"actions": [
"tree_planting",
"cool_roofs"
],
"priority": "medium",
"cost_estimate": "moderate"
})
return strategies
# Create specialized agents
environmental_monitor = Agent(
name="Environmental Monitor",
role="Data Collection",
goal="Collect environmental data",
instructions="Monitor and collect climate data",
tools=[collect_environmental_data]
)
urban_analyzer = Agent(
name="Urban Analyzer",
role="Urban Analysis",
goal="Analyze urban environment",
instructions="Assess urban factors affecting climate",
tools=[analyze_urban_factors]
)
climate_modeler = Agent(
name="Climate Modeler",
role="Climate Modeling",
goal="Model microclimate conditions",
instructions="Create detailed climate models",
tools=[model_microclimate]
)
impact_predictor = Agent(
name="Impact Predictor",
role="Impact Analysis",
goal="Predict climate impacts",
instructions="Assess potential climate impacts",
tools=[predict_impacts]
)
strategy_generator = Agent(
name="Strategy Generator",
role="Strategy Development",
goal="Generate adaptation strategies",
instructions="Develop climate adaptation strategies",
tools=[generate_adaptation_strategies]
)
# Create workflow tasks
monitoring_task = Task(
name="collect_data",
description="Collect environmental data",
expected_output="Environmental measurements",
agent=environmental_monitor,
is_start=True,
next_tasks=["analyze_urban"]
)
urban_task = Task(
name="analyze_urban",
description="Analyze urban factors",
expected_output="Urban analysis",
agent=urban_analyzer,
next_tasks=["model_climate"]
)
modeling_task = Task(
name="model_climate",
description="Model microclimate",
expected_output="Climate models",
agent=climate_modeler,
context=[monitoring_task, urban_task],
next_tasks=["predict_impacts"]
)
prediction_task = Task(
name="predict_impacts",
description="Predict climate impacts",
expected_output="Impact predictions",
agent=impact_predictor,
next_tasks=["generate_strategies"]
)
strategy_task = Task(
name="generate_strategies",
description="Generate adaptation strategies",
expected_output="Adaptation strategies",
agent=strategy_generator,
task_type="decision",
condition={
"immediate": ["collect_data"], # Continuous monitoring for high priority
"medium": "", # End workflow for medium priority
"low": "" # End workflow for low priority
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[environmental_monitor, urban_analyzer, climate_modeler,
impact_predictor, strategy_generator],
tasks=[monitoring_task, urban_task, modeling_task,
prediction_task, strategy_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Climate Impact Prediction Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nClimate Impact Analysis Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+203
View File
@@ -0,0 +1,203 @@
---
title: "Code Analysis Agent"
description: "Learn how to create AI agents for comprehensive code analysis and quality assessment."
icon: "code-merge"
---
```mermaid
flowchart LR
In[In] --> Analyzer[Code Analyzer]
Analyzer --> Quality[Quality Assessment]
Quality --> Metrics[Core Metrics]
Metrics --> Technical[Technical Review]
Technical --> Recommendations[Recommendations]
Recommendations --> Out[Out]
style In fill:#8B0000,color:#fff
style Analyzer fill:#2E8B57,color:#fff
style Quality fill:#2E8B57,color:#fff
style Metrics fill:#2E8B57,color:#fff
style Technical fill:#2E8B57,color:#fff
style Recommendations fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Code Analysis?
Code Analysis is a systematic process of evaluating source code to assess its quality, maintainability, performance, and security. This helps developers and organizations maintain high code standards and identify areas for improvement.
## Features
<CardGroup cols={2}>
<Card title="Quality Assessment" icon="chart-simple">
Comprehensive evaluation of code quality with numerical scoring.
</Card>
<Card title="Core Metrics Analysis" icon="gauge">
Analysis of architecture, maintainability, performance, and security.
</Card>
<Card title="Technical Assessment" icon="code">
Review of tech stack, complexity, and best practices adherence.
</Card>
<Card title="Risk Assessment" icon="shield">
Identification of potential risks and security vulnerabilities.
</Card>
<Card title="Recommendations" icon="lightbulb">
Actionable suggestions for improvements and enhancements.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents gitingest
```
</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
```
</Step>
<Step title="Create a file">
Create a new file `code_analysis.py` with the following code:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
from gitingest import ingest
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
return agents.start(context_text)
if __name__ == "__main__":
# Example usage
code_source = "https://github.com/openai/openai-python/tree/main/src/openai/cli/_api/chat" # GitHub URL or local directory
result = analyze_code(code_source)
print(result)
```
</Step>
</Steps>
## Understanding the Output
The code analysis generates a comprehensive report with the following components:
- Overall Quality Score (0-100)
- Core Metrics Analysis
- Architecture and Design Score
- Code Maintainability Score
- Performance Score
- Security Score
- Test Coverage Percentage
- Technical Assessment
- Technology Stack
- Complexity Metrics
- Best Practices Review
- Risk Assessment
- Recommendations
- Key Improvements
- Architecture Suggestions
- Security Enhancements
## 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>
<Card title="API Reference" icon="code" href="/api-reference">
Explore the complete API documentation
</Card>
</CardGroup>
+316
View File
@@ -0,0 +1,316 @@
---
title: "Crypto Validator"
description: "Learn how to create AI agents for post-quantum cryptographic scheme validation and security analysis."
icon: "key"
---
```mermaid
flowchart LR
In[In] --> Analyzer[Crypto Analyzer]
Analyzer --> Quantum[Attack Simulator]
Analyzer --> Perf[Performance Benchmarker]
Quantum --> Security[Implementation Assessor]
Perf --> Security
Security --> Compliance[Compliance Validator]
Compliance --> Out[Out]
style In fill:#8B0000,color:#fff
style Analyzer fill:#2E8B57,color:#fff
style Quantum fill:#2E8B57,color:#fff
style Perf fill:#2E8B57,color:#fff
style Security fill:#2E8B57,color:#fff
style Compliance fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Post-Quantum Cryptography?
Post-quantum cryptography focuses on developing cryptographic systems that are secure against both quantum and classical computers. This involves analyzing cryptographic schemes, simulating quantum attacks, and ensuring compliance with security standards.
## Features
<CardGroup cols={2}>
<Card title="Cryptographic Analysis" icon="shield-check">
Analyze quantum-resistant cryptographic schemes including lattice-based encryption and multivariate signatures.
</Card>
<Card title="Attack Simulation" icon="bug">
Test resistance against quantum attacks including Grover's algorithm and Shor's algorithm.
</Card>
<Card title="Performance Testing" icon="gauge-high">
Benchmark key generation, encryption/decryption speeds, and throughput metrics.
</Card>
<Card title="Security Assessment" icon="lock">
Evaluate implementation security including side-channel resistance and hardening measures.
</Card>
<Card title="Compliance Validation" icon="certificate">
Verify compliance with NIST PQC, Common Criteria, and FIPS standards.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_cryptographic_scheme():
"""Simulates cryptographic scheme analysis"""
schemes = [
{
"name": "lattice_based",
"type": "encryption",
"key_size": 2048,
"security_level": "AES-256 equivalent",
"parameters": {
"lattice_dimension": 1024,
"modulus": "q = 2^32 - 1",
"error_distribution": "discrete_gaussian"
}
},
{
"name": "multivariate",
"type": "signature",
"key_size": 4096,
"security_level": "SHA-384 equivalent",
"parameters": {
"variables": 128,
"equations": 128,
"field_size": "2^8"
}
}
]
return schemes[int(time.time()) % 2]
def simulate_quantum_attacks(scheme: Dict):
"""Simulates quantum attack scenarios"""
attacks = {
"grover_search": {
"effectiveness": "reduced",
"quantum_speedup": "quadratic",
"estimated_qubits": 2048,
"time_complexity": "O(2^n/2)"
},
"shor_algorithm": {
"effectiveness": "ineffective",
"quantum_speedup": "none",
"vulnerability": "resistant",
"classical_hardness": "maintained"
},
"quantum_hidden_subgroup": {
"effectiveness": "partial",
"applicability": "limited",
"mitigation": "parameter_adjustment"
}
}
return attacks
def benchmark_performance(scheme: Dict):
"""Benchmarks cryptographic performance"""
benchmarks = {
"key_generation": {
"time": 0.5 + (time.time() % 1) / 10, # seconds
"memory": 128 + (int(time.time()) % 64) # MB
},
"encryption_speed": {
"small_message": 0.001 + (time.time() % 1) / 1000, # seconds
"large_message": 0.1 + (time.time() % 1) / 10 # seconds
},
"decryption_speed": {
"small_message": 0.002 + (time.time() % 1) / 1000,
"large_message": 0.15 + (time.time() % 1) / 10
},
"throughput": {
"encryption": 100 + (int(time.time()) % 50), # MB/s
"decryption": 80 + (int(time.time()) % 40) # MB/s
}
}
return benchmarks
def assess_implementation(scheme: Dict, benchmarks: Dict):
"""Assesses implementation security"""
assessment = {
"side_channel_resistance": {
"timing_attacks": "protected",
"power_analysis": "partial_vulnerability",
"cache_attacks": "mitigated"
},
"implementation_hardening": {
"constant_time": True,
"memory_protection": True,
"error_handling": "secure"
},
"compiler_optimizations": {
"safety": "verified",
"performance_impact": -0.05 + (time.time() % 1) / 10
}
}
return assessment
def validate_compliance(scheme: Dict, assessment: Dict):
"""Validates compliance and standards"""
compliance = {
"nist_pqc": {
"status": "submitted",
"round": 3,
"requirements_met": True
},
"common_criteria": {
"evaluation_level": "EAL4+",
"protection_profile": "compliant"
},
"fips_140_3": {
"security_level": 3,
"validation_status": "in_process"
}
}
return compliance
# Create specialized agents
crypto_analyzer = Agent(
name="Crypto Analyzer",
role="Cryptographic Analysis",
goal="Analyze cryptographic schemes",
instructions="Evaluate quantum-resistant cryptographic schemes",
tools=[analyze_cryptographic_scheme]
)
attack_simulator = Agent(
name="Attack Simulator",
role="Attack Simulation",
goal="Simulate quantum attacks",
instructions="Test resistance against quantum attacks",
tools=[simulate_quantum_attacks]
)
performance_benchmarker = Agent(
name="Performance Benchmarker",
role="Performance Testing",
goal="Benchmark cryptographic performance",
instructions="Measure performance metrics",
tools=[benchmark_performance]
)
implementation_assessor = Agent(
name="Implementation Assessor",
role="Implementation Assessment",
goal="Assess implementation security",
instructions="Evaluate implementation security",
tools=[assess_implementation]
)
compliance_validator = Agent(
name="Compliance Validator",
role="Compliance Validation",
goal="Validate standards compliance",
instructions="Verify compliance with standards",
tools=[validate_compliance]
)
# Create workflow tasks
analysis_task = Task(
name="analyze_crypto",
description="Analyze cryptographic scheme",
expected_output="Cryptographic analysis",
agent=crypto_analyzer,
is_start=True,
next_tasks=["simulate_attacks", "benchmark_performance"]
)
attack_task = Task(
name="simulate_attacks",
description="Simulate quantum attacks",
expected_output="Attack simulation results",
agent=attack_simulator,
next_tasks=["assess_implementation"]
)
benchmark_task = Task(
name="benchmark_performance",
description="Benchmark performance",
expected_output="Performance benchmarks",
agent=performance_benchmarker,
next_tasks=["assess_implementation"]
)
assessment_task = Task(
name="assess_implementation",
description="Assess implementation",
expected_output="Implementation assessment",
agent=implementation_assessor,
context=[attack_task, benchmark_task],
next_tasks=["validate_compliance"]
)
compliance_task = Task(
name="validate_compliance",
description="Validate compliance",
expected_output="Compliance validation",
agent=compliance_validator,
task_type="decision",
condition={
"compliant": "", # End workflow if compliant
"non_compliant": ["assess_implementation"] # Reassess if non-compliant
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[crypto_analyzer, attack_simulator, performance_benchmarker,
implementation_assessor, compliance_validator],
tasks=[analysis_task, attack_task, benchmark_task,
assessment_task, compliance_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Quantum-Resistant Cryptography Validation Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nCryptography Validation Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+302
View File
@@ -0,0 +1,302 @@
---
title: "DeFi Market Maker"
description: "Learn how to create AI agents for decentralized finance market making and arbitrage."
icon: "chart-line"
---
```mermaid
flowchart LR
In[In] --> Market[Market Analyzer]
Market --> Arbitrage[Arbitrage Detector]
Market --> Liquidity[Liquidity Optimizer]
Arbitrage --> Risk[Risk Assessor]
Liquidity --> Risk
Risk --> Executor[Trade Executor]
Executor --> Out[Out]
style In fill:#8B0000,color:#fff
style Market fill:#2E8B57,color:#fff
style Arbitrage fill:#2E8B57,color:#fff
style Liquidity fill:#2E8B57,color:#fff
style Risk fill:#2E8B57,color:#fff
style Executor fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is DeFi Market Making?
Decentralized Finance (DeFi) market making involves providing liquidity to decentralized exchanges and automatically executing trades to capture arbitrage opportunities. This requires real-time analysis of market conditions, optimization of liquidity positions, and risk management.
## Features
<CardGroup cols={2}>
<Card title="Market Analysis" icon="chart-candlestick">
Real-time analysis of liquidity pools, market volatility, trading volumes, and gas prices.
</Card>
<Card title="Arbitrage Detection" icon="magnifying-glass-dollar">
Identification of profitable trading opportunities across different liquidity pools.
</Card>
<Card title="Liquidity Optimization" icon="water">
Optimization of liquidity distribution and pool ratios for maximum efficiency.
</Card>
<Card title="Risk Assessment" icon="shield-halved">
Comprehensive risk analysis including impermanent loss and smart contract risks.
</Card>
<Card title="Trade Execution" icon="money-bill-transfer">
Automated execution of optimized trades with performance monitoring.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_market_conditions():
"""Simulates market analysis"""
conditions = {
"liquidity_pools": {
"pool_A": {
"token_0": {"balance": 1000000, "price": 1.0},
"token_1": {"balance": 500000, "price": 2.0},
"total_value_locked": 2000000
},
"pool_B": {
"token_0": {"balance": 800000, "price": 1.0},
"token_1": {"balance": 400000, "price": 2.0},
"total_value_locked": 1600000
}
},
"market_volatility": 0.15 + (time.time() % 10) / 100,
"trading_volume_24h": 5000000 + (time.time() % 1000000),
"gas_prices": 50 + (time.time() % 30)
}
return conditions
def detect_arbitrage():
"""Simulates arbitrage opportunity detection"""
opportunities = [
{
"path": ["pool_A", "pool_B"],
"profit_potential": 0.02 + (time.time() % 5) / 100,
"required_capital": 10000,
"execution_cost": 50,
"risk_level": "low"
},
{
"path": ["pool_B", "pool_C"],
"profit_potential": 0.03 + (time.time() % 5) / 100,
"required_capital": 20000,
"execution_cost": 75,
"risk_level": "medium"
}
]
return opportunities[int(time.time()) % 2]
def optimize_liquidity(market_conditions: Dict):
"""Optimizes liquidity distribution"""
optimizations = {
"pool_A": {
"target_ratio": 2.0,
"suggested_actions": [
{
"action": "rebalance",
"token": "token_1",
"amount": 10000,
"direction": "add"
}
],
"expected_improvement": 0.05
},
"pool_B": {
"target_ratio": 1.8,
"suggested_actions": [
{
"action": "rebalance",
"token": "token_0",
"amount": 5000,
"direction": "remove"
}
],
"expected_improvement": 0.03
}
}
return optimizations
def assess_risks(arbitrage: Dict, optimizations: Dict):
"""Assesses potential risks"""
risk_assessment = {
"impermanent_loss_risk": 0.1 + (time.time() % 5) / 100,
"smart_contract_risk": "low",
"market_manipulation_risk": "medium" if arbitrage["profit_potential"] > 0.025 else "low",
"gas_price_risk": "high" if arbitrage["execution_cost"] > 60 else "medium",
"mitigation_strategies": [
"implement_slippage_protection",
"set_maximum_gas_price",
"use_multiple_liquidity_sources"
]
}
return risk_assessment
def execute_trades(arbitrage: Dict, risks: Dict):
"""Simulates trade execution"""
execution_results = {
"status": "success" if time.time() % 2 == 0 else "failed",
"executed_volume": arbitrage["required_capital"] * 0.95,
"actual_profit": arbitrage["profit_potential"] * 0.9,
"gas_used": arbitrage["execution_cost"] * 1.1,
"timestamp": time.time()
}
return execution_results
# Create specialized agents
market_analyzer = Agent(
name="Market Analyzer",
role="Market Analysis",
goal="Analyze market conditions",
instructions="Monitor and analyze DeFi market conditions",
tools=[analyze_market_conditions]
)
arbitrage_detector = Agent(
name="Arbitrage Detector",
role="Arbitrage Detection",
goal="Detect arbitrage opportunities",
instructions="Identify profitable trading opportunities",
tools=[detect_arbitrage]
)
liquidity_optimizer = Agent(
name="Liquidity Optimizer",
role="Liquidity Optimization",
goal="Optimize liquidity distribution",
instructions="Optimize pool liquidity ratios",
tools=[optimize_liquidity]
)
risk_assessor = Agent(
name="Risk Assessor",
role="Risk Assessment",
goal="Assess trading risks",
instructions="Evaluate potential risks and mitigation strategies",
tools=[assess_risks]
)
trade_executor = Agent(
name="Trade Executor",
role="Trade Execution",
goal="Execute optimized trades",
instructions="Execute trades based on analysis",
tools=[execute_trades]
)
# Create workflow tasks
market_task = Task(
name="analyze_market",
description="Analyze market conditions",
expected_output="Market analysis",
agent=market_analyzer,
is_start=True,
next_tasks=["detect_arbitrage", "optimize_liquidity"]
)
arbitrage_task = Task(
name="detect_arbitrage",
description="Detect arbitrage opportunities",
expected_output="Arbitrage opportunities",
agent=arbitrage_detector,
next_tasks=["assess_risks"]
)
liquidity_task = Task(
name="optimize_liquidity",
description="Optimize liquidity",
expected_output="Liquidity optimization",
agent=liquidity_optimizer,
context=[market_task],
next_tasks=["assess_risks"]
)
risk_task = Task(
name="assess_risks",
description="Assess trading risks",
expected_output="Risk assessment",
agent=risk_assessor,
context=[arbitrage_task, liquidity_task],
next_tasks=["execute_trades"]
)
execution_task = Task(
name="execute_trades",
description="Execute trades",
expected_output="Trade execution results",
agent=trade_executor,
task_type="decision",
condition={
"success": ["analyze_market"], # Continue monitoring if successful
"failed": ["optimize_liquidity"] # Reoptimize if failed
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[market_analyzer, arbitrage_detector, liquidity_optimizer,
risk_assessor, trade_executor],
tasks=[market_task, arbitrage_task, liquidity_task,
risk_task, execution_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting DeFi Market Making Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nMarket Making Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+80
View File
@@ -87,6 +87,86 @@ icon: "code"
>
Learn how to create AI agents for multilingual content generation and cultural adaptation.
</Card>
<Card
title="Climate Impact"
icon="cloud-sun"
href="/examples/climate-impact"
>
Learn how to create AI agents for climate impact analysis and adaptation strategies.
</Card>
<Card
title="Space Mission"
icon="rocket"
href="/examples/space-mission"
>
Learn how to create AI agents for space mission planning and resource optimization.
</Card>
<Card
title="Neural Architecture"
icon="network-wired"
href="/examples/neural-architecture"
>
Learn how to create AI agents for neural architecture search and optimization.
</Card>
<Card
title="DeFi Market Maker"
icon="money-bill-trend-up"
href="/examples/defi-market-maker"
>
Learn how to create AI agents for decentralized finance market making and liquidity provision.
</Card>
<Card
title="Quantum Optimiser"
icon="atom"
href="/examples/quantum-optimiser"
>
Learn how to create AI agents for quantum computing optimization and algorithm design.
</Card>
<Card
title="Medicine Protocol"
icon="prescription-bottle-medical"
href="/examples/medicine-protocol"
>
Learn how to create AI agents for medical protocol optimization and drug discovery.
</Card>
<Card
title="Crypto Validator"
icon="key"
href="/examples/crypto-validator"
>
Learn how to create AI agents for cryptocurrency validation and blockchain security.
</Card>
<Card
title="Research Assistant"
icon="microscope"
href="/examples/research-assistant"
>
Learn how to create AI agents for research analysis and experiment design.
</Card>
<Card
title="Vulnerability Detection"
icon="shield-check"
href="/examples/vulnerability-detection"
>
Learn how to create AI agents for vulnerability detection and analysis.
</Card>
<Card
title="Healthcare Diagnosis"
icon="stethoscope"
href="/examples/healthcare-diagnosis"
>
Learn how to create AI agents for medical diagnosis and treatment recommendations.
</Card>
</CardGroup>
## What's Next?
+265
View File
@@ -0,0 +1,265 @@
---
title: "Hackathon Judge Agent"
description: "Learn how to create AI agents for evaluating hackathon projects through video demonstrations."
icon: "trophy"
---
```mermaid
flowchart LR
In[In] --> Judge[Hackathon Judge]
Judge --> Scores[Project Scores]
Scores --> Analysis[Detailed Analysis]
Analysis --> Feedback[Feedback]
Feedback --> Recommendations[Recommendations]
Recommendations --> Out[Out]
style In fill:#8B0000,color:#fff
style Judge fill:#2E8B57,color:#fff
style Scores fill:#2E8B57,color:#fff
style Analysis fill:#2E8B57,color:#fff
style Feedback fill:#2E8B57,color:#fff
style Recommendations fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Hackathon Project Evaluation?
Hackathon Project Evaluation is an automated process for assessing hackathon projects through video demonstrations. It provides comprehensive scoring across multiple dimensions including innovation, technical complexity, and presentation quality, helping organizers make informed decisions and providing valuable feedback to participants.
## Features
<CardGroup cols={2}>
<Card title="Project Scoring" icon="star">
Comprehensive scoring system across multiple dimensions (0-100).
</Card>
<Card title="Technical Analysis" icon="microchip">
Evaluation of technical complexity and implementation quality.
</Card>
<Card title="Innovation Assessment" icon="lightbulb">
Analysis of creativity and unique project features.
</Card>
<Card title="Market Analysis" icon="chart-line">
Assessment of market potential and scalability.
</Card>
<Card title="Detailed Feedback" icon="comments">
Constructive feedback and specific recommendations for improvement.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents opencv-python moviepy
```
</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
```
</Step>
<Step title="Create a file">
Create a new file `hackathon_judge.py` with the following code:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
```
</Step>
</Steps>
## Understanding the Output
The hackathon project evaluation generates a comprehensive report with the following components:
- Scoring Metrics (0-100)
- Innovation Score
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
- Overall Score
- Qualitative Analysis
- Key Strengths
- Areas for Improvement
- Notable Features
- Technical Highlights
- Strategic Assessment
- Recommendations
- Market Potential
- Scalability Assessment
## 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>
<Card title="API Reference" icon="code" href="/api-reference">
Explore the complete API documentation
</Card>
</CardGroup>
+300
View File
@@ -0,0 +1,300 @@
---
title: "Medicine Protocol"
description: "Learn how to create AI agents for personalized medicine protocol generation and analysis."
icon: "stethoscope"
---
```mermaid
flowchart LR
In[In] --> Genetic[Genetic Analyzer]
In --> History[Patient History]
Genetic --> Interaction[Drug Interaction]
History --> Interaction
Interaction --> Protocol[Protocol Generator]
Protocol --> Simulation[Effectiveness Simulator]
Simulation --> Out[Out]
style In fill:#8B0000,color:#fff
style Genetic fill:#2E8B57,color:#fff
style History fill:#2E8B57,color:#fff
style Interaction fill:#2E8B57,color:#fff
style Protocol fill:#2E8B57,color:#fff
style Simulation fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Personalized Medicine?
Personalized medicine is an approach that tailors medical treatment to individual characteristics of each patient. It involves analyzing genetic markers, patient history, and drug interactions to create optimized treatment protocols.
## Features
<CardGroup cols={2}>
<Card title="Genetic Analysis" icon="dna">
Deep analysis of genetic markers including metabolism genes, risk factors, and drug response markers.
</Card>
<Card title="Patient History" icon="notes-medical">
Comprehensive evaluation of medical conditions, medications, allergies, and family history.
</Card>
<Card title="Drug Interaction" icon="pills">
Analysis of potential drug interactions based on genetic data and patient history.
</Card>
<Card title="Protocol Generation" icon="file-medical">
Creation of personalized treatment protocols with dosage adjustments and monitoring plans.
</Card>
<Card title="Treatment Simulation" icon="chart-line">
Prediction of treatment effectiveness, side effects, and adherence probability.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_genetic_markers():
"""Simulates genetic marker analysis"""
markers = {
"metabolism_genes": {
"CYP2D6": "rapid_metabolizer",
"CYP2C19": "normal_metabolizer",
"DPYD": "poor_metabolizer"
},
"risk_factors": {
"cardiovascular": "elevated",
"diabetes": "low",
"autoimmune": "moderate"
},
"drug_response_markers": {
"TPMT": "high_sensitivity",
"HLA-B*5701": "negative",
"UGT1A1": "normal"
}
}
return markers
def evaluate_patient_history():
"""Simulates patient history evaluation"""
history = {
"conditions": [
{"name": "hypertension", "duration": "5_years", "severity": "moderate"},
{"name": "arthritis", "duration": "2_years", "severity": "mild"}
],
"medications": [
{"name": "lisinopril", "response": "good", "side_effects": "minimal"},
{"name": "methotrexate", "response": "moderate", "side_effects": "mild"}
],
"allergies": ["penicillin", "sulfa"],
"family_history": ["diabetes", "heart_disease"]
}
return history
def analyze_drug_interactions(genetic_data: Dict, patient_history: Dict):
"""Analyzes potential drug interactions"""
interactions = []
medications = [med["name"] for med in patient_history["medications"]]
for med in medications:
interactions.append({
"medication": med,
"genetic_impact": "significant" if genetic_data["metabolism_genes"]["CYP2D6"] == "rapid_metabolizer" else "normal",
"risk_level": "high" if med in patient_history["allergies"] else "low",
"monitoring_needed": True if genetic_data["metabolism_genes"]["DPYD"] == "poor_metabolizer" else False
})
return interactions
def generate_protocol(genetic_data: Dict, interactions: List[Dict]):
"""Generates treatment protocol"""
protocol = {
"primary_treatment": {
"medication": "custom_formulation_A",
"dosage": "adjusted_based_on_metabolism",
"frequency": "twice_daily",
"monitoring": {
"type": "blood_levels",
"frequency": "weekly"
}
},
"alternatives": [
{
"medication": "custom_formulation_B",
"conditions": ["genetic_compatibility", "no_interactions"]
}
],
"precautions": []
}
if genetic_data["metabolism_genes"]["CYP2D6"] == "rapid_metabolizer":
protocol["precautions"].append("increase_monitoring_frequency")
if any(i["risk_level"] == "high" for i in interactions):
protocol["precautions"].append("alternative_medication_needed")
return protocol
def simulate_effectiveness(protocol: Dict):
"""Simulates treatment effectiveness"""
simulation = {
"efficacy_prediction": 0.85 + (time.time() % 2) / 10,
"side_effect_risk": 0.15 + (time.time() % 1) / 10,
"adherence_probability": 0.9 + (time.time() % 1) / 10,
"expected_outcomes": [
"symptom_reduction_80_percent",
"minimal_side_effects",
"good_tolerance"
]
}
return simulation
# Create specialized agents
genetic_analyzer = Agent(
name="Genetic Analyzer",
role="Genetic Analysis",
goal="Analyze genetic markers",
instructions="Evaluate genetic markers and variants",
tools=[analyze_genetic_markers]
)
history_analyzer = Agent(
name="History Analyzer",
role="History Analysis",
goal="Analyze patient history",
instructions="Evaluate medical history and conditions",
tools=[evaluate_patient_history]
)
interaction_analyzer = Agent(
name="Interaction Analyzer",
role="Drug Interaction",
goal="Analyze drug interactions",
instructions="Evaluate potential drug interactions",
tools=[analyze_drug_interactions]
)
protocol_generator = Agent(
name="Protocol Generator",
role="Protocol Generation",
goal="Generate treatment protocol",
instructions="Create personalized treatment protocol",
tools=[generate_protocol]
)
effectiveness_simulator = Agent(
name="Effectiveness Simulator",
role="Treatment Simulation",
goal="Simulate treatment effectiveness",
instructions="Predict treatment outcomes",
tools=[simulate_effectiveness]
)
# Create workflow tasks
genetic_task = Task(
name="analyze_genetics",
description="Analyze genetic markers",
expected_output="Genetic analysis",
agent=genetic_analyzer,
is_start=True,
next_tasks=["analyze_history"]
)
history_task = Task(
name="analyze_history",
description="Analyze patient history",
expected_output="History analysis",
agent=history_analyzer,
next_tasks=["analyze_interactions"]
)
interaction_task = Task(
name="analyze_interactions",
description="Analyze drug interactions",
expected_output="Interaction analysis",
agent=interaction_analyzer,
context=[genetic_task, history_task],
next_tasks=["generate_protocol"]
)
protocol_task = Task(
name="generate_protocol",
description="Generate treatment protocol",
expected_output="Treatment protocol",
agent=protocol_generator,
context=[genetic_task, interaction_task],
next_tasks=["simulate_effectiveness"]
)
simulation_task = Task(
name="simulate_effectiveness",
description="Simulate treatment effectiveness",
expected_output="Effectiveness simulation",
agent=effectiveness_simulator,
task_type="decision",
condition={
"high": "", # End workflow if high effectiveness
"medium": ["generate_protocol"], # Adjust protocol if medium
"low": ["analyze_interactions"] # Reanalyze if low
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[genetic_analyzer, history_analyzer, interaction_analyzer,
protocol_generator, effectiveness_simulator],
tasks=[genetic_task, history_task, interaction_task,
protocol_task, simulation_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Personalized Medicine Protocol Generation...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nProtocol Generation Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+284
View File
@@ -0,0 +1,284 @@
---
title: "Neural Architecture"
description: "Learn how to create AI agents for neural architecture search and optimization."
icon: "brain"
---
```mermaid
flowchart LR
In[In] --> Hardware[Hardware Analyzer]
Hardware --> Generator[Architecture Generator]
Generator --> Hyperparams[Hyperparameter Optimizer]
Hyperparams --> Performance[Performance Estimator]
Performance --> Deployment[Deployment Optimizer]
Deployment --> Out[Out]
style In fill:#8B0000,color:#fff
style Hardware fill:#2E8B57,color:#fff
style Generator fill:#2E8B57,color:#fff
style Hyperparams fill:#2E8B57,color:#fff
style Performance fill:#2E8B57,color:#fff
style Deployment fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Neural Architecture Search?
Neural Architecture Search (NAS) is an automated process for designing optimal neural network architectures. It involves analyzing hardware constraints, generating candidate architectures, optimizing hyperparameters, and configuring deployment settings to create efficient and performant models.
## Features
<CardGroup cols={2}>
<Card title="Hardware Analysis" icon="microchip">
Analysis of GPU memory, compute capability, bandwidth, and thermal constraints.
</Card>
<Card title="Architecture Generation" icon="diagram-project">
Creation of candidate architectures including transformers and CNNs with optimized structures.
</Card>
<Card title="Hyperparameter Tuning" icon="sliders">
Optimization of learning rates, batch sizes, optimizers, and regularization parameters.
</Card>
<Card title="Performance Estimation" icon="gauge-high">
Prediction of model accuracy, training time, memory requirements, and FLOPS.
</Card>
<Card title="Deployment Optimization" icon="rocket">
Configuration of quantization, pruning, and batching for efficient deployment.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_hardware_constraints():
"""Simulates hardware analysis"""
constraints = {
"gpu_memory": 16 * 1024, # MB
"compute_capability": "7.5",
"memory_bandwidth": 900, # GB/s
"tensor_cores": True,
"max_power_consumption": 300, # Watts
"thermal_limits": 85 # Celsius
}
return constraints
def generate_architecture_candidates():
"""Generates candidate architectures"""
candidates = [
{
"type": "transformer",
"layers": 12 + (int(time.time()) % 6),
"attention_heads": 8,
"embedding_dim": 512,
"estimated_params": 125_000_000
},
{
"type": "cnn",
"layers": 50 + (int(time.time()) % 50),
"filters": [64, 128, 256, 512],
"estimated_params": 25_000_000
}
]
return candidates[int(time.time()) % 2]
def optimize_hyperparameters(architecture: Dict):
"""Optimizes hyperparameters"""
optimization = {
"learning_rate": 0.001 + (time.time() % 9) / 10000,
"batch_size": 32 * (1 + int(time.time()) % 4),
"optimizer": "adam",
"weight_decay": 0.0001,
"dropout_rate": 0.1 + (time.time() % 3) / 10,
"activation": "gelu" if architecture["type"] == "transformer" else "relu"
}
return optimization
def estimate_performance(architecture: Dict, hyperparams: Dict):
"""Estimates model performance"""
performance = {
"estimated_accuracy": 0.85 + (time.time() % 10) / 100,
"estimated_training_time": {
"hours": 24 + (int(time.time()) % 24),
"gpu_hours": 96
},
"memory_requirements": {
"training": architecture["estimated_params"] * 4 / (1024 * 1024), # GB
"inference": architecture["estimated_params"] * 2 / (1024 * 1024) # GB
},
"flops_count": architecture["estimated_params"] * 2
}
return performance
def optimize_deployment(architecture: Dict, performance: Dict):
"""Optimizes deployment configuration"""
deployment = {
"quantization": {
"method": "dynamic",
"precision": "int8",
"estimated_speedup": 2.5
},
"pruning": {
"method": "magnitude",
"target_sparsity": 0.3,
"estimated_size_reduction": 0.6
},
"batching": {
"max_batch_size": 32,
"dynamic_batching": True
}
}
return deployment
# Create specialized agents
hardware_analyzer = Agent(
name="Hardware Analyzer",
role="Hardware Analysis",
goal="Analyze hardware constraints",
instructions="Evaluate available hardware resources",
tools=[analyze_hardware_constraints]
)
architecture_generator = Agent(
name="Architecture Generator",
role="Architecture Generation",
goal="Generate neural architectures",
instructions="Create candidate neural architectures",
tools=[generate_architecture_candidates]
)
hyperparameter_optimizer = Agent(
name="Hyperparameter Optimizer",
role="Hyperparameter Optimization",
goal="Optimize hyperparameters",
instructions="Find optimal hyperparameter settings",
tools=[optimize_hyperparameters]
)
performance_estimator = Agent(
name="Performance Estimator",
role="Performance Estimation",
goal="Estimate model performance",
instructions="Predict model performance metrics",
tools=[estimate_performance]
)
deployment_optimizer = Agent(
name="Deployment Optimizer",
role="Deployment Optimization",
goal="Optimize deployment settings",
instructions="Configure optimal deployment",
tools=[optimize_deployment]
)
# Create workflow tasks
hardware_task = Task(
name="analyze_hardware",
description="Analyze hardware constraints",
expected_output="Hardware analysis",
agent=hardware_analyzer,
is_start=True,
next_tasks=["generate_architecture"]
)
architecture_task = Task(
name="generate_architecture",
description="Generate architecture candidates",
expected_output="Architecture candidates",
agent=architecture_generator,
next_tasks=["optimize_hyperparameters"]
)
hyperparameter_task = Task(
name="optimize_hyperparameters",
description="Optimize hyperparameters",
expected_output="Hyperparameter settings",
agent=hyperparameter_optimizer,
context=[architecture_task],
next_tasks=["estimate_performance"]
)
performance_task = Task(
name="estimate_performance",
description="Estimate performance",
expected_output="Performance estimates",
agent=performance_estimator,
context=[architecture_task, hyperparameter_task],
next_tasks=["optimize_deployment"]
)
deployment_task = Task(
name="optimize_deployment",
description="Optimize deployment",
expected_output="Deployment configuration",
agent=deployment_optimizer,
context=[architecture_task, performance_task],
task_type="decision",
condition={
"success": ["generate_architecture"], # Try new architecture
"failure": ["optimize_hyperparameters"] # Reoptimize hyperparameters
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[hardware_analyzer, architecture_generator, hyperparameter_optimizer,
performance_estimator, deployment_optimizer],
tasks=[hardware_task, architecture_task, hyperparameter_task,
performance_task, deployment_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Neural Architecture Search Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nArchitecture Search Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+279
View File
@@ -0,0 +1,279 @@
---
title: "Quantum Optimiser"
description: "Learn how to create AI agents for quantum circuit optimization and performance analysis."
icon: "atom"
---
```mermaid
flowchart LR
In[In] --> Analyzer[Circuit Analyzer]
Analyzer --> Finder[Optimization Finder]
Finder --> Optimizer[Circuit Optimizer]
Optimizer --> Benchmarker[Performance Benchmarker]
Benchmarker --> Validator[Results Validator]
Validator --> Out[Out]
style In fill:#8B0000,color:#fff
style Analyzer fill:#2E8B57,color:#fff
style Finder fill:#2E8B57,color:#fff
style Optimizer fill:#2E8B57,color:#fff
style Benchmarker fill:#2E8B57,color:#fff
style Validator fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Quantum Circuit Optimization?
Quantum circuit optimization is the process of improving quantum algorithms by reducing circuit depth, minimizing gate count, and enhancing execution efficiency while maintaining computational fidelity. This is crucial for making quantum algorithms practical on real quantum hardware.
## Features
<CardGroup cols={2}>
<Card title="Circuit Analysis" icon="microchip">
Deep analysis of quantum circuit metrics including depth, gate counts, and qubit usage.
</Card>
<Card title="Optimization Detection" icon="magnifying-glass">
Identification of optimization opportunities through gate reduction and parallel execution.
</Card>
<Card title="Performance Simulation" icon="gauge-high">
Simulation of optimization results with improvement metrics and success probabilities.
</Card>
<Card title="Benchmark Testing" icon="chart-line">
Comprehensive benchmarking of execution time, fidelity, and resource usage.
</Card>
<Card title="Result Validation" icon="check-double">
Validation of optimization results ensuring performance gains and fidelity maintenance.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_quantum_circuit():
"""Simulates quantum circuit analysis"""
circuit_metrics = {
"depth": 15 + (int(time.time()) % 10),
"gates": {
"single_qubit": 25 + (int(time.time()) % 15),
"two_qubit": 10 + (int(time.time()) % 8),
"measurement": 5 + (int(time.time()) % 3)
},
"qubits": 8 + (int(time.time()) % 4)
}
return circuit_metrics
def identify_optimization_opportunities(metrics: Dict):
"""Identifies potential optimization areas"""
opportunities = []
if metrics["depth"] > 20:
opportunities.append({
"type": "depth_reduction",
"potential": "high",
"technique": "parallel_gates"
})
if metrics["gates"]["two_qubit"] > 15:
opportunities.append({
"type": "gate_reduction",
"potential": "medium",
"technique": "gate_decomposition"
})
return opportunities
def simulate_optimization(opportunities: List[Dict]):
"""Simulates optimization results"""
results = []
for opt in opportunities:
improvement = {
"high": 0.3 + (time.time() % 2) / 10,
"medium": 0.2 + (time.time() % 2) / 10,
"low": 0.1 + (time.time() % 2) / 10
}
results.append({
"type": opt["type"],
"improvement": improvement[opt["potential"]],
"success_probability": 0.8 + (time.time() % 2) / 10
})
return results
def benchmark_performance(original: Dict, optimized: List[Dict]):
"""Benchmarks optimization performance"""
benchmarks = {
"execution_time": {
"original": 100 + (int(time.time()) % 50),
"optimized": 70 + (int(time.time()) % 30)
},
"fidelity": {
"original": 0.9 + (time.time() % 1) / 10,
"optimized": 0.85 + (time.time() % 1) / 10
},
"resource_usage": {
"original": original["qubits"],
"optimized": original["qubits"] - len(optimized)
}
}
return benchmarks
def validate_results(benchmarks: Dict):
"""Validates optimization results"""
validations = {
"performance_gain": (benchmarks["execution_time"]["original"] -
benchmarks["execution_time"]["optimized"]) /
benchmarks["execution_time"]["original"],
"fidelity_maintained": benchmarks["fidelity"]["optimized"] > 0.8,
"resource_efficient": benchmarks["resource_usage"]["optimized"] <
benchmarks["resource_usage"]["original"]
}
return validations
# Create specialized agents
circuit_analyzer = Agent(
name="Circuit Analyzer",
role="Circuit Analysis",
goal="Analyze quantum circuit structure",
instructions="Evaluate quantum circuit metrics",
tools=[analyze_quantum_circuit]
)
optimization_finder = Agent(
name="Optimization Finder",
role="Optimization Discovery",
goal="Identify optimization opportunities",
instructions="Find potential optimization techniques",
tools=[identify_optimization_opportunities]
)
optimizer = Agent(
name="Circuit Optimizer",
role="Circuit Optimization",
goal="Optimize quantum circuit",
instructions="Apply optimization techniques",
tools=[simulate_optimization]
)
benchmarker = Agent(
name="Performance Benchmarker",
role="Performance Analysis",
goal="Benchmark optimization results",
instructions="Measure performance improvements",
tools=[benchmark_performance]
)
validator = Agent(
name="Results Validator",
role="Validation",
goal="Validate optimization results",
instructions="Ensure optimization quality",
tools=[validate_results]
)
# Create workflow tasks
analysis_task = Task(
name="analyze_circuit",
description="Analyze quantum circuit",
expected_output="Circuit metrics",
agent=circuit_analyzer,
is_start=True,
next_tasks=["find_optimizations"]
)
optimization_task = Task(
name="find_optimizations",
description="Find optimization opportunities",
expected_output="Optimization opportunities",
agent=optimization_finder,
next_tasks=["optimize_circuit"]
)
optimization_execution_task = Task(
name="optimize_circuit",
description="Execute circuit optimization",
expected_output="Optimization results",
agent=optimizer,
next_tasks=["benchmark_performance"]
)
benchmark_task = Task(
name="benchmark_performance",
description="Benchmark optimization",
expected_output="Performance metrics",
agent=benchmarker,
next_tasks=["validate_results"],
context=[analysis_task, optimization_execution_task]
)
validation_task = Task(
name="validate_results",
description="Validate optimization results",
expected_output="Validation results",
agent=validator,
task_type="decision",
condition={
"True": "", # End workflow if validation passes
"False": ["find_optimizations"] # Retry optimization if validation fails
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[circuit_analyzer, optimization_finder, optimizer,
benchmarker, validator],
tasks=[analysis_task, optimization_task, optimization_execution_task,
benchmark_task, validation_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Quantum Algorithm Optimization Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nOptimization Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+274
View File
@@ -0,0 +1,274 @@
---
title: "Research Assistant"
description: "Learn how to create AI agents for research analysis and experiment design."
icon: "microscope"
---
```mermaid
flowchart LR
In[In] --> Analyzer[Paper Analyzer]
Analyzer --> Gap[Gap Identifier]
Gap --> Designer[Experiment Designer]
Designer --> Validator[Methodology Validator]
Validator --> Impact[Impact Predictor]
Impact --> Out[Out]
style In fill:#8B0000,color:#fff
style Analyzer fill:#2E8B57,color:#fff
style Gap fill:#2E8B57,color:#fff
style Designer fill:#2E8B57,color:#fff
style Validator fill:#2E8B57,color:#fff
style Impact fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Research Analysis?
Research Analysis is a systematic process of analyzing scientific papers, identifying knowledge gaps, designing experiments, validating methodologies, and predicting research impact. This helps researchers make informed decisions about their research direction and experimental design.
## Features
<CardGroup cols={2}>
<Card title="Paper Analysis" icon="book">
Analysis of research papers with topic identification and impact assessment.
</Card>
<Card title="Gap Identification" icon="magnifying-glass">
Discovery of research gaps with significance and potential evaluation.
</Card>
<Card title="Experiment Design" icon="flask">
Creation of experimental methodologies with resource planning.
</Card>
<Card title="Methodology Validation" icon="check-double">
Validation of experimental design with statistical power and feasibility checks.
</Card>
<Card title="Impact Prediction" icon="chart-line">
Prediction of research impact with novelty and breakthrough probability.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_research_papers():
"""Simulates research paper analysis"""
papers = [
{
"topic": "quantum_computing",
"gaps": ["error_correction", "scalability"],
"methodology": "experimental",
"impact_factor": 8.5
},
{
"topic": "machine_learning",
"gaps": ["interpretability", "robustness"],
"methodology": "theoretical",
"impact_factor": 7.8
}
]
return papers[int(time.time()) % 2]
def identify_knowledge_gaps(papers: Dict):
"""Identifies research gaps"""
gaps = []
for gap in papers["gaps"]:
gaps.append({
"area": gap,
"significance": "high" if papers["impact_factor"] > 8 else "medium",
"research_potential": 0.8 + (time.time() % 2) / 10
})
return gaps
def design_experiment(gaps: List[Dict]):
"""Designs experimental methodology"""
experiments = []
for gap in gaps:
experiments.append({
"area": gap["area"],
"methodology": {
"type": "quantitative",
"duration": "3_months",
"resources_needed": ["equipment_A", "dataset_B"],
"expected_outcome": "validation_metrics"
},
"priority": gap["significance"]
})
return experiments
def validate_methodology(experiments: List[Dict]):
"""Validates experimental design"""
validations = []
for exp in experiments:
validations.append({
"area": exp["area"],
"statistical_power": 0.9 + (time.time() % 1) / 10,
"resource_feasibility": 0.8 + (time.time() % 1) / 10,
"ethical_compliance": True,
"recommendations": []
})
return validations
def predict_impact(experiments: List[Dict], validations: List[Dict]):
"""Predicts research impact"""
predictions = []
for exp, val in zip(experiments, validations):
predictions.append({
"area": exp["area"],
"potential_impact": val["statistical_power"] * 10,
"novelty_score": 0.7 + (time.time() % 3) / 10,
"breakthrough_probability": 0.5 + (time.time() % 4) / 10
})
return predictions
# Create specialized agents
paper_analyzer = Agent(
name="Paper Analyzer",
role="Research Analysis",
goal="Analyze research papers",
instructions="Review and analyze scientific papers",
tools=[analyze_research_papers]
)
gap_identifier = Agent(
name="Gap Identifier",
role="Gap Analysis",
goal="Identify knowledge gaps",
instructions="Identify research opportunities",
tools=[identify_knowledge_gaps]
)
experiment_designer = Agent(
name="Experiment Designer",
role="Experimental Design",
goal="Design research experiments",
instructions="Create experimental methodologies",
tools=[design_experiment]
)
methodology_validator = Agent(
name="Methodology Validator",
role="Validation",
goal="Validate experimental design",
instructions="Ensure methodology validity",
tools=[validate_methodology]
)
impact_predictor = Agent(
name="Impact Predictor",
role="Impact Analysis",
goal="Predict research impact",
instructions="Assess potential impact",
tools=[predict_impact]
)
# Create workflow tasks
analysis_task = Task(
name="analyze_papers",
description="Analyze research papers",
expected_output="Paper analysis results",
agent=paper_analyzer,
is_start=True,
next_tasks=["identify_gaps"]
)
gap_task = Task(
name="identify_gaps",
description="Identify knowledge gaps",
expected_output="Research gaps",
agent=gap_identifier,
next_tasks=["design_experiments"]
)
design_task = Task(
name="design_experiments",
description="Design experiments",
expected_output="Experimental designs",
agent=experiment_designer,
next_tasks=["validate_methodology"]
)
validation_task = Task(
name="validate_methodology",
description="Validate methodology",
expected_output="Validation results",
agent=methodology_validator,
next_tasks=["predict_impact"]
)
prediction_task = Task(
name="predict_impact",
description="Predict research impact",
expected_output="Impact predictions",
agent=impact_predictor,
task_type="decision",
condition={
"high": "", # End workflow if high impact
"medium": ["design_experiments"], # Refine if medium impact
"low": ["identify_gaps"] # Restart if low impact
},
context=[design_task, validation_task]
)
# Create workflow
workflow = PraisonAIAgents(
agents=[paper_analyzer, gap_identifier, experiment_designer,
methodology_validator, impact_predictor],
tasks=[analysis_task, gap_task, design_task,
validation_task, prediction_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Research Assistant Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nResearch Analysis Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+313
View File
@@ -0,0 +1,313 @@
---
title: "Space Mission"
description: "Learn how to create AI agents for space mission planning and resource optimization."
icon: "rocket"
---
```mermaid
flowchart LR
In[In] --> Mission[Mission Analyzer]
Mission --> Resources[Resource Calculator]
Resources --> Contingency[Contingency Planner]
Contingency --> Optimizer[Resource Optimizer]
Optimizer --> Simulator[Scenario Simulator]
Simulator --> Out[Out]
style In fill:#8B0000,color:#fff
style Mission fill:#2E8B57,color:#fff
style Resources fill:#2E8B57,color:#fff
style Contingency fill:#2E8B57,color:#fff
style Optimizer fill:#2E8B57,color:#fff
style Simulator fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Space Mission Planning?
Space Mission Planning is a complex process that involves analyzing mission parameters, calculating resource requirements, planning contingencies, optimizing resource allocation, and simulating various scenarios. This ensures the safety and success of space missions by carefully managing resources and preparing for potential emergencies.
## Features
<CardGroup cols={2}>
<Card title="Mission Analysis" icon="satellite">
Analysis of mission duration, crew size, orbital parameters, and objectives.
</Card>
<Card title="Resource Calculation" icon="calculator">
Computation of life support, power, and propellant requirements.
</Card>
<Card title="Contingency Planning" icon="shield">
Planning for power failures, life support malfunctions, and other emergencies.
</Card>
<Card title="Resource Optimization" icon="chart-line">
Optimization of resource allocation with buffers for contingencies.
</Card>
<Card title="Scenario Simulation" icon="vr-cardboard">
Simulation of nominal operations and emergency scenarios.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def analyze_mission_parameters():
"""Simulates mission parameter analysis"""
parameters = {
"duration": 180, # days
"crew_size": 4,
"orbital_parameters": {
"altitude": 400, # km
"inclination": 51.6, # degrees
"period": 92.68 # minutes
},
"mission_objectives": [
"scientific_research",
"satellite_deployment",
"space_station_maintenance"
]
}
return parameters
def calculate_resource_requirements(params: Dict):
"""Calculates required resources"""
requirements = {
"life_support": {
"oxygen": params["duration"] * params["crew_size"] * 0.84, # kg
"water": params["duration"] * params["crew_size"] * 2.5, # liters
"food": params["duration"] * params["crew_size"] * 1.8 # kg
},
"power": {
"daily_consumption": 30 + (params["crew_size"] * 5), # kWh
"peak_demand": 45 + (params["crew_size"] * 8), # kW
"backup_capacity": 72 # hours
},
"propellant": {
"main_engine": 2000, # kg
"attitude_control": 500, # kg
"reserve": 300 # kg
}
}
return requirements
def plan_contingencies(requirements: Dict):
"""Plans contingency scenarios"""
contingencies = [
{
"scenario": "power_failure",
"probability": 0.05,
"impact": "critical",
"resources_needed": {
"backup_power": requirements["power"]["daily_consumption"] * 3,
"repair_equipment": ["solar_panel_kit", "power_distribution_unit"]
}
},
{
"scenario": "life_support_malfunction",
"probability": 0.03,
"impact": "severe",
"resources_needed": {
"oxygen_reserve": requirements["life_support"]["oxygen"] * 0.2,
"repair_parts": ["filter_system", "pressure_regulators"]
}
}
]
return contingencies[int(time.time()) % 2]
def optimize_allocation(requirements: Dict, contingencies: Dict):
"""Optimizes resource allocation"""
allocation = {
"primary_resources": {
"life_support": {
"nominal": requirements["life_support"],
"buffer": 0.15 # 15% buffer
},
"power": {
"nominal": requirements["power"],
"buffer": 0.2 # 20% buffer
}
},
"contingency_resources": {
"type": contingencies["scenario"],
"allocation": contingencies["resources_needed"],
"priority": "high" if contingencies["impact"] == "critical" else "medium"
}
}
return allocation
def simulate_mission_scenarios(allocation: Dict):
"""Simulates various mission scenarios"""
scenarios = {
"nominal_operations": {
"success_rate": 0.95,
"resource_utilization": 0.85,
"efficiency_rating": 0.9
},
"emergency_scenarios": [
{
"type": "power_reduction",
"duration": 48, # hours
"impact": "moderate",
"resolution_success": 0.88
},
{
"type": "life_support_adjustment",
"duration": 24, # hours
"impact": "minor",
"resolution_success": 0.92
}
]
}
return scenarios
# Create specialized agents
mission_analyzer = Agent(
name="Mission Analyzer",
role="Mission Analysis",
goal="Analyze mission parameters",
instructions="Evaluate mission requirements and constraints",
tools=[analyze_mission_parameters]
)
resource_calculator = Agent(
name="Resource Calculator",
role="Resource Calculation",
goal="Calculate resource requirements",
instructions="Determine required resources for mission",
tools=[calculate_resource_requirements]
)
contingency_planner = Agent(
name="Contingency Planner",
role="Contingency Planning",
goal="Plan for contingencies",
instructions="Develop contingency scenarios and plans",
tools=[plan_contingencies]
)
resource_optimizer = Agent(
name="Resource Optimizer",
role="Resource Optimization",
goal="Optimize resource allocation",
instructions="Optimize resource distribution",
tools=[optimize_allocation]
)
scenario_simulator = Agent(
name="Scenario Simulator",
role="Scenario Simulation",
goal="Simulate mission scenarios",
instructions="Simulate various mission scenarios",
tools=[simulate_mission_scenarios]
)
# Create workflow tasks
mission_task = Task(
name="analyze_mission",
description="Analyze mission parameters",
expected_output="Mission parameters",
agent=mission_analyzer,
is_start=True,
next_tasks=["calculate_resources"]
)
resource_task = Task(
name="calculate_resources",
description="Calculate resource requirements",
expected_output="Resource requirements",
agent=resource_calculator,
next_tasks=["plan_contingencies"]
)
contingency_task = Task(
name="plan_contingencies",
description="Plan contingencies",
expected_output="Contingency plans",
agent=contingency_planner,
context=[resource_task],
next_tasks=["optimize_resources"]
)
optimization_task = Task(
name="optimize_resources",
description="Optimize resource allocation",
expected_output="Resource allocation",
agent=resource_optimizer,
context=[resource_task, contingency_task],
next_tasks=["simulate_scenarios"]
)
simulation_task = Task(
name="simulate_scenarios",
description="Simulate scenarios",
expected_output="Simulation results",
agent=scenario_simulator,
task_type="decision",
condition={
"nominal_operations": "", # End workflow if nominal
"emergency_scenarios": ["optimize_resources"] # Reoptimize if emergency
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[mission_analyzer, resource_calculator, contingency_planner,
resource_optimizer, scenario_simulator],
tasks=[mission_task, resource_task, contingency_task,
optimization_task, simulation_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Space Mission Resource Optimization Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nResource Optimization Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+277
View File
@@ -0,0 +1,277 @@
---
title: "Vulnerability Detection"
description: "Learn how to create AI agents for vulnerability detection and analysis."
icon: "shield-check"
---
```mermaid
flowchart LR
In[In] --> Scanner[Pattern Scanner]
Scanner --> Vector[Vector Analyzer]
Vector --> Simulator[Exploit Simulator]
Simulator --> Generator[Signature Generator]
Generator --> Validator[Finding Validator]
Validator --> Out[Out]
style In fill:#8B0000,color:#fff
style Scanner fill:#2E8B57,color:#fff
style Vector fill:#2E8B57,color:#fff
style Simulator fill:#2E8B57,color:#fff
style Generator fill:#2E8B57,color:#fff
style Validator fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## What is Vulnerability Detection?
Vulnerability Detection is a systematic process of identifying, analyzing, and validating security vulnerabilities in code. It involves pattern scanning, attack vector analysis, exploitation simulation, signature generation, and finding validation to ensure robust security measures are in place.
## Features
<CardGroup cols={2}>
<Card title="Pattern Scanning" icon="magnifying-glass">
Detection of buffer overflows, SQL injections, and race conditions.
</Card>
<Card title="Attack Vector Analysis" icon="route">
Analysis of attack paths, complexity, and CVSS scores.
</Card>
<Card title="Exploit Simulation" icon="bug">
Simulation of exploitation attempts with success rate and detection time.
</Card>
<Card title="Signature Generation" icon="fingerprint">
Creation of vulnerability signatures with reliability metrics.
</Card>
<Card title="Finding Validation" icon="check-double">
Validation of findings with confidence and reproducibility scores.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import Dict, List
import asyncio
def scan_code_patterns():
"""Simulates code pattern scanning"""
patterns = [
{
"type": "buffer_overflow",
"severity": "critical",
"location": "memory_management",
"frequency": 3
},
{
"type": "sql_injection",
"severity": "high",
"location": "database_interface",
"frequency": 2
},
{
"type": "race_condition",
"severity": "medium",
"location": "thread_handling",
"frequency": 1
}
]
return patterns[int(time.time()) % 3]
def analyze_attack_vectors(pattern: Dict):
"""Analyzes potential attack vectors"""
vectors = []
severity_scores = {"critical": 9.5, "high": 8.0, "medium": 6.5}
base_score = severity_scores[pattern["type"]]
vectors.append({
"type": pattern["type"],
"attack_path": f"exploit_{pattern['location']}",
"complexity": "high" if pattern["frequency"] < 2 else "medium",
"cvss_score": base_score + (time.time() % 1)
})
return vectors
def simulate_exploitation(vectors: List[Dict]):
"""Simulates exploitation attempts"""
results = []
for vector in vectors:
results.append({
"vector": vector["type"],
"success_rate": 0.7 + (time.time() % 3) / 10,
"detection_time": 100 + (int(time.time()) % 50),
"mitigation_possible": vector["complexity"] != "high"
})
return results
def generate_signatures(results: List[Dict]):
"""Generates vulnerability signatures"""
signatures = []
for result in results:
signatures.append({
"pattern": f"signature_{result['vector']}",
"reliability": result['success_rate'],
"false_positive_rate": 0.1 + (time.time() % 2) / 10,
"detection_speed": result['detection_time']
})
return signatures
def validate_findings(signatures: List[Dict]):
"""Validates vulnerability findings"""
validations = []
for sig in signatures:
validations.append({
"signature": sig["pattern"],
"confidence": sig["reliability"] * (1 - sig["false_positive_rate"]),
"reproducibility": 0.8 + (time.time() % 2) / 10,
"severity": "critical" if sig["reliability"] > 0.8 else "high"
})
return validations
# Create specialized agents
pattern_scanner = Agent(
name="Pattern Scanner",
role="Code Analysis",
goal="Scan for suspicious patterns",
instructions="Analyze code for potential vulnerabilities",
tools=[scan_code_patterns]
)
vector_analyzer = Agent(
name="Vector Analyzer",
role="Attack Vector Analysis",
goal="Analyze attack vectors",
instructions="Identify potential attack paths",
tools=[analyze_attack_vectors]
)
exploit_simulator = Agent(
name="Exploit Simulator",
role="Exploitation Testing",
goal="Simulate exploitation attempts",
instructions="Test potential vulnerabilities",
tools=[simulate_exploitation]
)
signature_generator = Agent(
name="Signature Generator",
role="Signature Creation",
goal="Generate vulnerability signatures",
instructions="Create detection signatures",
tools=[generate_signatures]
)
finding_validator = Agent(
name="Finding Validator",
role="Validation",
goal="Validate findings",
instructions="Verify vulnerability findings",
tools=[validate_findings]
)
# Create workflow tasks
scanning_task = Task(
name="scan_patterns",
description="Scan code patterns",
expected_output="Suspicious patterns",
agent=pattern_scanner,
is_start=True,
next_tasks=["analyze_vectors"]
)
vector_task = Task(
name="analyze_vectors",
description="Analyze attack vectors",
expected_output="Attack vectors",
agent=vector_analyzer,
next_tasks=["simulate_exploits"]
)
simulation_task = Task(
name="simulate_exploits",
description="Simulate exploits",
expected_output="Exploitation results",
agent=exploit_simulator,
next_tasks=["generate_signatures"]
)
signature_task = Task(
name="generate_signatures",
description="Generate signatures",
expected_output="Vulnerability signatures",
agent=signature_generator,
next_tasks=["validate_findings"]
)
validation_task = Task(
name="validate_findings",
description="Validate findings",
expected_output="Validation results",
agent=finding_validator,
task_type="decision",
condition={
"critical": ["scan_patterns"], # Continue scanning if critical
"high": ["analyze_vectors"], # Reanalyze if high
"medium": "" # End workflow if medium
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[pattern_scanner, vector_analyzer, exploit_simulator,
signature_generator, finding_validator],
tasks=[scanning_task, vector_task, simulation_task,
signature_task, validation_task],
process="workflow",
verbose=True
)
async def main():
print("\nStarting Vulnerability Detection Workflow...")
print("=" * 50)
# Run workflow
results = await workflow.astart()
# Print results
print("\nVulnerability Detection Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
asyncio.run(main())
```
</Step>
</Steps>
## 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>
+244
View File
@@ -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>
+2 -2
View File
@@ -12,7 +12,7 @@ icon: "images"
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
pip install praisonaiagents opencv-python moviepy
```
</Step>
<Step title="Set API Key">
@@ -71,7 +71,7 @@ icon: "images"
<Step title="Install Package">
Install the PraisonAI package:
```bash
pip install praisonai
pip install praisonai opencv-python moviepy
```
</Step>
<Step title="Set API Key">
+352
View File
@@ -0,0 +1,352 @@
---
title: "RAG Agents"
description: "Learn how to create AI agents that can efficiently interact with vector databases for knowledge retrieval and storage."
icon: "database"
---
```mermaid
flowchart LR
In[Input] --> RAGAgent[("RAG Agent")]
VDB[(Vector DB)] --> RAGAgent
RAGAgent --> Task[Knowledge Task]
Task --> |Query| VDB
Task --> Out[Output]
style In fill:#8B0000,color:#fff
style RAGAgent fill:#2E8B57,color:#fff,shape:circle
style VDB fill:#4169E1,color:#fff,shape:cylinder
style Task fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
A knowledge-centric workflow where RAG (Retrieval Augmented Generation) agents interact with vector databases to store and retrieve information efficiently, enabling sophisticated question-answering and information retrieval capabilities.
## Quick Start
<Steps>
<Step title="Install Package">
Install PraisonAI Agents with knowledge 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 `app.py`:
```python
from praisonaiagents import Agent
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["small.pdf"], # Indexing
)
agent.start("What is KAG in one line?") # Retrieval
```
</Step>
</Steps>
## Data Indexing and Retrieval Agents
<Note>
Indexing and Ingestion are relatively the same.
</Note>
```mermaid
flowchart LR
subgraph In[Input]
PDF[PDF]
TXT[TXT]
MD[MD]
end
subgraph Router[Vector Store]
DB[(Vector DB)]
end
subgraph Out[Agents]
A1[Agent 1]
A2[Agent 2]
A3[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 knowledge-based agent is without any configuration:
```python
from praisonaiagents import Agent
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["small.pdf"] # Indexing
)
agent.start("What is KAG in one line?") # Retrieval
```
### 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="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["small.pdf"], # Indexing
knowledge_config=config # Configuration
)
agent.start("What is KAG in one line?") # Retrieval
```
### 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
```
## Retrieval Agents
<Note>
Retrieval is the process of querying the vector database for information.
Considering there is data already in the Vector Database.
</Note>
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `rag_agent.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
# Define the configuration for the Knowledge instance
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
}
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="gpt-4o-mini"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Retrieval : Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
```
</Step>
<Step title="Start Agents">
Type this in your terminal to run your agents:
```bash
python rag_agent.py
```
</Step>
</Steps>
<Note>
**Requirements**
- Python 3.10 or higher
- OpenAI API key. Generate OpenAI API key [here](https://platform.openai.com/api-keys). Use Other models using [this guide](/models).
- ChromaDB or other supported vector database
</Note>
### Adding Knowledge to RAG Agents
```python
from praisonaiagents import Agent
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison",
}
}
}
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["small.pdf"], # Indexing
knowledge_config=config # Configuration
)
agent.start("What is KAG in one line?") # Retrieval
```
## Understanding RAG Agents
<Card title="What are RAG Agents?" icon="question">
RAG (Retrieval Augmented Generation) agents enable:
- Efficient knowledge retrieval
- Semantic search capabilities
- Persistent knowledge storage
- Context-aware responses
</Card>
## Features
<CardGroup cols={2}>
<Card title="RAG Architecture" icon="database">
Store and manage vector embeddings efficiently.
</Card>
<Card title="Semantic Search" icon="magnifying-glass">
Find relevant information using semantic similarity.
</Card>
<Card title="Knowledge Integration" icon="brain">
Seamlessly integrate with existing knowledge bases.
</Card>
<Card title="Context Management" icon="layer-group">
Handle complex contextual queries and responses.
</Card>
</CardGroup>
## Troubleshooting
<CardGroup cols={2}>
<Card title="RAG Issues" icon="triangle-exclamation">
If RAG system isn't working:
- Check database configuration
- Verify connection settings
- Enable verbose mode for debugging
</Card>
<Card title="Query Issues" icon="gauge-high">
If queries aren't returning expected results:
- Check embedding quality
- Verify search parameters
- Monitor similarity thresholds
</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 results, ensure your vector database is properly configured and indexed for your specific use case.
</Note>
+138
View File
@@ -0,0 +1,138 @@
---
title: "Repetitive Agents"
description: "Learn how to create AI agents that can efficiently handle repetitive tasks through automated loops."
icon: "repeat"
---
```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
```
A workflow optimization pattern where agents handle repetitive tasks through automated loops, processing multiple instances efficiently while maintaining consistency.
## Quick Start
<Steps>
<Step title="Install Package">
First, install the PraisonAI Agents package:
```bash
pip install praisonaiagents
```
</Step>
<Step title="Set API Key">
Set your OpenAI API key as an environment variable in your terminal:
```bash
export OPENAI_API_KEY=your_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `repetitive_agent.py` with the basic setup:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
agent = Agent(
instructions="You are a loop agent that creating a loop of tasks."
)
task = Task(
description="Create the list of tasks to be looped through.",
agent=agent,
task_type="loop",
input_file="tasks.csv"
)
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
process="workflow",
max_iter=30
)
agents.start()
```
</Step>
<Step title="Start Agents">
Type this in your terminal to run your agents:
```bash
python repetitive_agent.py
```
</Step>
</Steps>
<Note>
**Requirements**
- Python 3.10 or higher
- OpenAI API key. Generate OpenAI API key [here](https://platform.openai.com/api-keys). Use Other models using [this guide](/models).
</Note>
## Understanding Repetitive Agents
<Card title="What are Repetitive Agents?" icon="question">
Repetitive agents enable:
- Automated task loops
- Batch processing
- Consistent task execution
- Efficient handling of multiple similar tasks
</Card>
## Features
<CardGroup cols={2}>
<Card title="Task Looping" icon="repeat">
Process multiple tasks through automated loops.
</Card>
<Card title="Batch Processing" icon="layer-group">
Handle multiple similar tasks efficiently.
</Card>
<Card title="Input Management" icon="file-csv">
Process tasks from structured input files.
</Card>
<Card title="Progress Tracking" icon="chart-line">
Monitor task completion and progress.
</Card>
</CardGroup>
## Troubleshooting
<CardGroup cols={2}>
<Card title="Loop Issues" icon="triangle-exclamation">
If loops aren't working as expected:
- Verify input file format
- Check task configurations
- Enable verbose mode for debugging
</Card>
<Card title="Performance Issues" icon="gauge-high">
If processing is slow:
- Check batch sizes
- Verify resource allocation
- Monitor memory usage
</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 results, ensure your input files are properly formatted and your task configurations are appropriate for your use case.
</Note>
+13 -26
View File
@@ -6,9 +6,7 @@ icon: "book-open"
## What is PraisonAI?
<Note>
PraisonAI is a powerful Multi-Agent Framework for building and deploying AI agents that can understand, reason, and execute complex tasks autonomously.
</Note>
PraisonAI is a powerful Multi-Agent Framework for building and deploying AI agents that can understand, reason, and execute complex tasks autonomously.
<CardGroup cols={1}>
<Card title="Welcome to PraisonAI" icon="wand-magic-sparkles">
Build powerful autonomous agents that understand, decide, and execute with unprecedented capability.
@@ -26,45 +24,34 @@ graph LR
Agent2 --> Output([✓ Output])
Process -.-> Agent1
%% Styling for main elements
style Start fill:#2D3047,stroke:#7C90A0,color:#fff
style Output fill:#2D3047,stroke:#7C90A0,color:#fff
style Process fill:#5C80BC,stroke:#7C90A0,color:#fff
%% Define subgraphs for agents and their tasks
subgraph Agent1[" "]
subgraph Agent1[ ]
Task1[📋 Task]
AgentIcon1[🤖 AI Agent]
Tools1[🔧 Tools]
Task1 --- AgentIcon1
AgentIcon1 --- Tools1
style Task1 fill:#2D3047,stroke:#7C90A0,color:#fff
style AgentIcon1 fill:#5C80BC,stroke:#7C90A0,color:#fff
style Tools1 fill:#2D3047,stroke:#7C90A0,color:#fff
end
subgraph Agent2[" "]
subgraph Agent2[ ]
Task2[📋 Task]
AgentIcon2[🤖 AI Agent]
Tools2[🔧 Tools]
Task2 --- AgentIcon2
AgentIcon2 --- Tools2
style Task2 fill:#2D3047,stroke:#7C90A0,color:#fff
style AgentIcon2 fill:#5C80BC,stroke:#7C90A0,color:#fff
style Tools2 fill:#2D3047,stroke:#7C90A0,color:#fff
end
%% Style for agent containers
style Agent1 fill:#1B1F3B,stroke:#7C90A0,color:#fff
style Agent2 fill:#1B1F3B,stroke:#7C90A0,color:#fff
%% Global styles
classDef default fill:#2D3047,stroke:#7C90A0,color:#fff
linkStyle default stroke:#7C90A0,stroke-width:2px
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
```
<br />
<CardGroup cols={2}>
+37 -5
View File
@@ -70,6 +70,10 @@
{
"name": "UI",
"url": "/ui"
},
{
"name": "Tools",
"url": "/tools"
}
],
"navigation": [
@@ -104,7 +108,8 @@
"features/autonomous-workflow",
"features/parallelisation",
"features/promptchaining",
"features/evaluator-optimiser"
"features/evaluator-optimiser",
"features/repetitive"
]
},
{
@@ -112,6 +117,7 @@
"pages": [
"features/autoagents",
"features/selfreflection",
"features/rag",
"features/reasoning",
"features/multimodal",
"features/langchain",
@@ -120,7 +126,8 @@
"features/codeagent",
"features/mathagent",
"features/structured",
"features/callbacks"
"features/callbacks",
"features/chat-with-pdf"
]
},
{
@@ -135,6 +142,7 @@
"models/anthropic",
"models/cohere",
"models/mistral",
"models/deepseek",
"models/other"
]
},
@@ -142,6 +150,8 @@
"group": "Examples",
"pages": [
"examples/examples",
"examples/code-analysis",
"examples/hackathon-judge",
"examples/predictive-maintenance",
"examples/emergency-response",
"examples/code-review",
@@ -151,7 +161,16 @@
"examples/customer-service",
"examples/smart-city",
"examples/multilingual-content",
"examples/adaptive-learning"
"examples/adaptive-learning",
"examples/crypto-validator",
"examples/space-mission",
"examples/neural-architecture",
"examples/defi-market-maker",
"examples/medicine-protocol",
"examples/climate-impact",
"examples/vulnerability-detection",
"examples/research-assistant",
"examples/quantum-optimiser"
]
},
{
@@ -177,6 +196,8 @@
{
"group": "Tools",
"pages": [
"tools/tools",
"tools/langchain_tools",
"tools/duckduckgo_tools",
"tools/arxiv_tools",
"tools/calculator_tools",
@@ -194,7 +215,6 @@
"tools/xml_tools",
"tools/yaml_tools",
"tools/yfinance_tools",
"tools",
"tools/custom",
"tools/tools_class",
"tools/gpt",
@@ -226,7 +246,18 @@
"pages": [
"ui/overview",
"ui/gradio",
"ui/streamlit",
{
"group": "Streamlit",
"icon": "pen-paintbrush",
"pages": [
"ui/streamlit",
"ui/streamlit/code-analysis-streamlit",
"ui/streamlit/hackathon-judge-streamlit",
"ui/streamlit/ollama-streamlit",
"ui/streamlit/deepseek-streamlit",
"ui/streamlit/gemini-streamlit"
]
},
"ui/ui",
"ui/chat",
"ui/code"
@@ -245,6 +276,7 @@
"developers/wrapper-tools",
"developers/googlecolab",
"developers/googlecolab-tools",
"developers/local-development",
"deploy"
]
},
+178 -1
View File
@@ -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>
+253
View File
@@ -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
View File
@@ -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) |
+138 -4
View File
@@ -1,9 +1,143 @@
---
title: Quick Start
description: Build your first AI agent with PraisonAI
icon: bolt
title: "Quick Start"
description: "Create AI Agents and make them work for you in just a few lines of code."
icon: "bolt"
---
# Basic
<Tabs>
<Tab title="Code">
<Steps>
<Step title="Install Package">
Install the PraisonAI Agents package:
```bash
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="Create Agents">
Create `app.py`:
<CodeGroup>
```python Single Agent
from praisonaiagents import Agent, PraisonAIAgents
# Create a simple agent
summarise_agent = Agent(instructions="Summarise Photosynthesis")
# Run the agent
agents = PraisonAIAgents(agents=[summarise_agent])
agents.start()
```
```python Multiple Agents
from praisonaiagents import Agent, PraisonAIAgents
# Create agents with specific roles
diet_agent = Agent(
instructions="Give me 5 healthy food recipes",
)
blog_agent = Agent(
instructions="Write a blog post about the food recipes",
)
# Run multiple agents
agents = PraisonAIAgents(agents=[diet_agent, blog_agent])
agents.start()
```
</CodeGroup>
</Step>
<Step title="Run Agents">
Execute your script:
```bash
python app.py
```
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="Set API Key">
```bash
export OPENAI_API_KEY=your_openai_key
```
</Step>
<Step title="Create Config">
Create `agents.yaml`:
<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>
</Tabs>
<Note>
**Prerequisites**
- Python 3.10 or higher
- OpenAI API key (get it [here](https://platform.openai.com/api-keys))
- For other LLM providers, see [Models](/models)
</Note>
# Advanced
## Providing Detailed Tasks to Agents (Optional)
<Tabs>
<Tab title="Code">
<Steps>
@@ -180,7 +314,7 @@ praisonai --init create movie script about cat in mars
</Tabs>
## Creating Custom Tool for Agents
## Creating Custom Tool for Agents (Optional)
<Info>
Tools makes the Agent powerful.
+2 -1
View File
@@ -1,5 +1,6 @@
---
title: "Create Custom Tools"
title: "Low Code Custom Tools"
sidebarTitle: "Low Code Custom Tools"
description: "Step-by-step guide for creating and implementing custom tools in PraisonAI, including examples and configuration instructions"
icon: "wrench"
---
+219
View File
@@ -0,0 +1,219 @@
---
title: "LangChain Agent"
sidebarTitle: "LangChain Agent"
description: "Learn how to use LangChain tools and utilities with PraisonAI agents."
icon: "link-simple"
---
## Quick Start
<Tabs>
<Tab title="Code">
<Steps>
<Step title="Install Package">
First, install the required packages:
```bash
pip install praisonaiagents langchain-community wikipedia
```
</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
```
</Step>
<Step title="Create a file">
Create a new file `app.py` with the basic setup:
<CodeGroup>
```python Single Tool
from praisonaiagents import Agent, Task, PraisonAIAgents
from langchain_community.utilities import WikipediaAPIWrapper
# Create an agent with Wikipedia tool
agent = Agent(
name="WikiAgent",
role="Research Assistant",
goal="Search Wikipedia for accurate information",
backstory="I am an AI assistant specialized in Wikipedia research",
tools=[WikipediaAPIWrapper],
self_reflect=False
)
# Create a research task
task = Task(
name="wiki_search",
description="Research 'Artificial Intelligence' on Wikipedia",
expected_output="Comprehensive information from Wikipedia articles",
agent=agent
)
# Create and start the workflow
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
verbose=True
)
agents.start()
```
```python Multiple Tools
from praisonaiagents import Agent, Task, PraisonAIAgents
from langchain_community.tools import YouTubeSearchTool
from langchain_community.utilities import WikipediaAPIWrapper
# Create YouTube search agent
agent = Agent(
name="SearchAgent",
role="Research Assistant",
goal="Search for information from YouTube",
backstory="I am an AI assistant that can search YouTube for relevant videos.",
tools=[YouTubeSearchTool],
self_reflect=False
)
# Create Wikipedia research agent
agent2 = Agent(
name="WikiAgent",
role="Research Assistant",
goal="Search for information from Wikipedia",
backstory="I am an AI assistant that can search Wikipedia for accurate information.",
tools=[WikipediaAPIWrapper],
self_reflect=False
)
# Create YouTube search task
task = Task(
name="search_task",
description="Search for information about 'AI advancements' on YouTube",
expected_output="Relevant information from YouTube videos",
agent=agent
)
# Create Wikipedia research task
task2 = Task(
name="wiki_task",
description="Search for information about 'AI advancements' on Wikipedia",
expected_output="Comprehensive information from Wikipedia articles",
agent=agent2
)
# Create and start the workflow
agents = PraisonAIAgents(
agents=[agent, agent2],
tasks=[task, task2],
verbose=True
)
agents.start()
```
</CodeGroup>
</Step>
<Step title="Start Agents">
Type this in your terminal to run your agents:
```bash
python app.py
```
</Step>
</Steps>
</Tab>
<Tab title="No Code">
<Steps>
<Step title="Install Package">
(Upcoming Feature)
Install the PraisonAI package:
```bash
pip 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_api_key_here
```
</Step>
<Step title="Create a file">
Create a new file `agents.yaml` with the basic setup:
```yaml
framework: praisonai
process: sequential
roles:
researcher:
name: SearchAgent
role: Research Assistant
goal: Search for information from multiple sources
backstory: I am an AI assistant that can search YouTube and Wikipedia.
tools:
- youtube_search
- wikipedia
tasks:
search_task:
name: search_task
description: Search for information about 'AI advancements' on both YouTube and Wikipedia
expected_output: Combined information from YouTube videos and Wikipedia articles
```
</Step>
<Step title="Start Agents">
Type this in your terminal to run your agents:
```bash
praisonai agents.yaml
```
</Step>
</Steps>
</Tab>
</Tabs>
<Note>
**Requirements**
- Python 3.10 or higher
- OpenAI API key. Generate OpenAI API key [here](https://platform.openai.com/api-keys)
- LangChain compatible tools and utilities
</Note>
## Understanding LangChain Integration
<Card title="What is LangChain Integration?" icon="question">
LangChain integration enables agents to:
- Use LangChain's extensive tool ecosystem
- Access various data sources and APIs
- Leverage pre-built utilities and wrappers
- Combine multiple tools in a single agent
- Extend agent capabilities with community tools
</Card>
## Features
<CardGroup cols={2}>
<Card title="Tool Integration" icon="plug">
Seamlessly use LangChain tools with PraisonAI agents.
</Card>
<Card title="Multiple Sources" icon="database">
Access various data sources through LangChain utilities.
</Card>
<Card title="Community Tools" icon="users">
Leverage the extensive LangChain community ecosystem.
</Card>
<Card title="Custom Tools" icon="wrench">
Create and integrate custom LangChain tools.
</Card>
</CardGroup>
## Next Steps
<CardGroup cols={2}>
<Card title="Memory Integration" icon="brain" href="../concepts/memory">
Learn how to combine LangChain tools with agent memory
</Card>
<Card title="Custom Tools" icon="wrench" href="./tools">
Create your own custom tools for agents
</Card>
</CardGroup>
<Note>
For optimal results, ensure all required dependencies are installed and API keys are properly configured for each tool.
</Note>
+40
View File
@@ -12,6 +12,46 @@ export REDDIT_CLIENT_SECRET=xxxxxx
export REDDIT_CLIENT_ID=xxxxxx
```
[USER] in this format script:APP:v1.0(by/u/USERNAME)
```bash
pip install praisonai langchain_community praw
```
```bash
export OPENAI_API_KEY="Enter your API key"
```
## Code
### Single Agent
```python
from praisonaiagents import Agent
from langchain_community.tools.reddit_search.tool import RedditSearchRun
agent = Agent(name="RedditSearchAgent",instructions="Search Reddit for information", tools=[RedditSearchRun],)
agent.start("Search Reddit for information about the latest AI advancements in subreddit all")
```
### Multi Agents
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
from langchain_community.tools.reddit_search.tool import RedditSearchRun
agent = Agent(name="RedditSearchAgent",instructions="Search Reddit for information", tools=[RedditSearchRun],)
task = Task(description="Search Reddit for information about the latest AI news in subreddit all", agent=agent)
agents = PraisonAIAgents(agents=[agent],tasks=[task])
agents.start()
```
## No Code
tools.py
```python
+647
View File
@@ -0,0 +1,647 @@
---
title: "AI Agents with Tools"
sidebarTitle: "Tools"
description: "Learn how to create AI agents that can use tools to interact with external systems and perform actions."
icon: "screwdriver-wrench"
---
```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
```
| Feature | [Knowledge](/concepts/knowledge) | [Tools](/concepts/tools) |
|---------|--------------------------------|---------------------------|
| Purpose | Static reference information | Dynamic interaction capabilities |
| Access | Read-only reference | Execute actions and commands |
| Updates | Manual through files | Real-time through tool calls |
| Storage | Knowledge base | Assigned to specific agents |
| Persistence | Permanent until changed | Available during agent execution |
## Quick Start
Tools are functions that agents can use to interact with external systems and perform actions. They are essential for creating agents that can do more than just process text.
## Creating Custom Tool
<Steps>
<Step>
Create any function that you want to use as a tool, that performs a specific task.
```python
from duckduckgo_search import DDGS
from typing import List, Dict
# Tool Implementation
def internet_search_tool(query: str) -> List[Dict]:
"""
Perform Internet Search using DuckDuckGo
Args:
query (str): The search query string
Returns:
List[Dict]: List of search results containing title, URL, and snippet
"""
results = []
ddgs = DDGS()
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
return results
```
</Step>
<Step>
Assign the tool to an agent
```python
data_agent = Agent(
name="DataCollector",
role="Search Specialist",
goal="Perform internet searches to collect relevant information.",
backstory="Expert in finding and organising internet data.",
tools=[internet_search_tool], ## Add the tool to the agent i.e the function name
)
```
</Step>
</Steps>
<Card title="That's it!">
<Check>You have created a custom tool and assigned it to an agent.</Check>
</Card>
## Implementing Tools Full Code Example
<Tabs>
<Tab title="Code">
<Steps>
<Step title="Install PraisonAI">
Install the core package:
```bash Terminal
pip install praisonaiagents duckduckgo-search
```
</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 Agent with Tool">
Create `app.py`
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
from duckduckgo_search import DDGS
from typing import List, Dict
# 1. Tool Implementation
def internet_search_tool(query: str) -> List[Dict]:
"""
Perform Internet Search using DuckDuckGo
Args:
query (str): The search query string
Returns:
List[Dict]: List of search results containing title, URL, and snippet
"""
results = []
ddgs = DDGS()
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
return results
# 2. Assign the tool to an agent
data_agent = Agent(
name="DataCollector",
role="Search Specialist",
goal="Perform internet searches to collect relevant information.",
backstory="Expert in finding and organising internet data.",
tools=[internet_search_tool],
self_reflect=False
)
# 3. Task Definition
collect_task = Task(
description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.",
expected_output="List of search results with titles, URLs, and snippets.",
agent=data_agent,
name="collect_data",
)
# 4. Start Agents
agents = PraisonAIAgents(
agents=[data_agent],
tasks=[collect_task],
process="sequential"
)
agents.start()
```
</Step>
<Step title="Start Agents">
Execute your script:
```bash Terminal
python app.py
```
</Step>
</Steps>
</Tab>
<Tab title="No Code">
<Steps>
<Step title="Install PraisonAI">
Install the core package and duckduckgo_search package:
```bash Terminal
pip install praisonai duckduckgo_search
```
</Step>
<Step title="Create Custom Tool">
<Info>
To add additional tools/features you need some coding which can be generated using ChatGPT or any LLM
</Info>
Create a new file `tools.py` with the following content:
```python
from duckduckgo_search import DDGS
from typing import List, Dict
# 1. Tool
def internet_search_tool(query: str) -> List[Dict]:
"""
Perform Internet Search
"""
results = []
ddgs = DDGS()
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
return results
```
</Step>
<Step title="Create Agent">
Create a new file `agents.yaml` with the following content:
```yaml
framework: praisonai
topic: create movie script about cat in mars
roles:
scriptwriter:
backstory: Expert in dialogue and script structure, translating concepts into
scripts.
goal: Write a movie script about a cat in Mars
role: Scriptwriter
tools:
- internet_search_tool # <-- Tool assigned to Agent here
tasks:
scriptwriting_task:
description: Turn the story concept into a production-ready movie script,
including dialogue and scene details.
expected_output: Final movie script with dialogue and scene details.
```
</Step>
<Step title="Start Agents">
Execute your script:
```bash Terminal
praisonai agents.yaml
```
</Step>
</Steps>
</Tab>
</Tabs>
## In-build Tools in PraisonAI
<CardGroup cols={2}>
<Card title="Search Tools" icon="magnifying-glass" href="/tools/search">
Tools for searching and retrieving information from various sources
</Card>
<Card title="Python Tools" icon="python" href="/tools/python_tools">
Essential Python utilities for data manipulation and scripting
</Card>
<Card title="Spider Tools" icon="spider" href="/tools/spider_tools">
Web crawling and scraping capabilities for data extraction
</Card>
<Card title="Arxiv Tools" icon="book" href="/tools/arxiv_tools">
Access and search academic papers from arXiv repository
</Card>
<Card title="Newspaper Tools" icon="newspaper" href="/tools/newspaper_tools">
Extract and parse content from news articles and websites
</Card>
<Card title="DuckDB Tools" icon="database" href="/tools/duckdb_tools">
Fast analytical SQL database operations and queries
</Card>
<Card title="DuckDuckGo Tools" icon="duck" href="/tools/duckduckgo_tools">
Web search functionality using DuckDuckGo's API
</Card>
<Card title="Calculator Tools" icon="calculator" href="/tools/calculator_tools">
Perform mathematical calculations and conversions
</Card>
<Card title="YAML Tools" icon="file-code" href="/tools/yaml_tools">
Parse and manipulate YAML format data
</Card>
<Card title="JSON Tools" icon="brackets-curly" href="/tools/json_tools">
Handle JSON data structures and operations
</Card>
<Card title="Pandas Tools" icon="table" href="/tools/pandas_tools">
Data analysis and manipulation using Pandas
</Card>
<Card title="YFinance Tools" icon="chart-line" href="/tools/yfinance_tools">
Fetch financial market data from Yahoo Finance
</Card>
<Card title="Shell Tools" icon="terminal" href="/tools/shell_tools">
Execute shell commands and system operations
</Card>
<Card title="Wikipedia Tools" icon="book-open" href="/tools/wikipedia_tools">
Access and search Wikipedia articles and data
</Card>
<Card title="XML Tools" icon="code" href="/tools/xml_tools">
Process and manipulate XML format data
</Card>
<Card title="File Tools" icon="file" href="/tools/file_tools">
File system operations and management utilities
</Card>
<Card title="Excel Tools" icon="file-excel" href="/tools/excel_tools">
Work with Excel spreadsheets and workbooks
</Card>
<Card title="CSV Tools" icon="file-csv" href="/tools/csv_tools">
Handle CSV file operations and transformations
</Card>
</CardGroup>
## Tools Overview
<CardGroup cols={3}>
<Card
title="Search Tools"
icon="magnifying-glass"
iconType="solid"
>
Tools for searching and retrieving information from various sources
</Card>
<Card
title="File Tools"
icon="file"
iconType="solid"
>
Tools for reading, writing, and manipulating files
</Card>
<Card
title="API Tools"
icon="code"
iconType="solid"
>
Tools for interacting with external APIs and services
</Card>
</CardGroup>
## Advanced Tool Features
### Tool Configuration
<Frame>
```python
def configured_tool(
query: str,
max_results: int = 5,
timeout: int = 10
) -> List[Dict]:
"""
Example of a configurable tool
Args:
query (str): Search query
max_results (int): Maximum number of results
timeout (int): Request timeout in seconds
Returns:
List[Dict]: Search results
"""
# Tool implementation
pass
```
</Frame>
### Tool Chaining
<Frame>
```python
def chain_tools(input_data: str) -> Dict:
"""
Example of chaining multiple tools
Args:
input_data (str): Input data
Returns:
Dict: Processed results
"""
# 1. Search for data
search_results = internet_search_tool(input_data)
# 2. Process results
processed_data = process_tool(search_results)
# 3. Format output
return format_tool(processed_data)
```
</Frame>
### Tool Categories
<CardGroup cols={3}>
<Card title="Data Collection Tools">
- Web scraping
- API integration
- Database queries
</Card>
<Card title="Processing Tools">
- Data transformation
- Text analysis
- Image processing
</Card>
<Card title="Output Tools">
- File generation
- Report creation
- Data visualization
</Card>
</CardGroup>
## Tool Integration
### Adding Tools to Agents
<Frame>
```python
# Multiple tools
agent = Agent(
name="MultiTool Agent",
tools=[
internet_search_tool,
file_processing_tool,
api_integration_tool
]
)
```
</Frame>
### Tool Dependencies
<Frame>
```python
# Tool with dependencies
def advanced_tool(data: Dict) -> Dict:
"""
Tool that depends on external libraries
Args:
data (Dict): Input data
Returns:
Dict: Processed data
"""
try:
import required_library
# Tool implementation
return processed_result
except ImportError:
raise Exception("Required library not installed")
```
</Frame>
## Tool Guidelines
<CardGroup cols={2}>
<Card title="Best Practices">
1. **Type Hints**
- Use Python type hints
- Define clear input/output types
- Document complex types
2. **Documentation**
- Write clear docstrings
- Explain parameters
- Provide usage examples
3. **Error Handling**
- Handle exceptions gracefully
- Return meaningful errors
- Validate inputs
</Card>
<Card title="Tool Types">
1. **Search Tools**
- Web search
- Database queries
- Document search
2. **File Tools**
- Read/write operations
- File conversion
- Data extraction
3. **API Tools**
- REST API calls
- GraphQL queries
- Service integration
</Card>
</CardGroup>
## Best Practices Summary
<Note>
Following these best practices will help you create robust, efficient, and secure tools in PraisonAI.
</Note>
<CardGroup cols={1}>
<Card title="Design Principles" icon="compass-drafting" iconType="solid">
<AccordionGroup>
<Accordion title="Single Responsibility">
Each tool should have one clear purpose and do it well. Avoid creating tools that try to do too many things.
```python
# Good Example
def process_image(image: np.array) -> np.array:
return processed_image
# Avoid
def process_and_save_and_upload(image):
# Too many responsibilities
pass
```
</Accordion>
<Accordion title="Clear Interfaces">
Define explicit input/output types and maintain consistent parameter naming.
```python
def search_tool(
query: str,
max_results: int = 10
) -> List[Dict[str, Any]]:
"""
Search for information with clear parameters
"""
pass
```
</Accordion>
<Accordion title="Documentation">
Always include detailed docstrings and type hints.
```python
def analyze_text(
text: str,
language: str = "en"
) -> Dict[str, float]:
"""
Analyze text sentiment and emotions.
Args:
text: Input text to analyze
language: ISO language code
Returns:
Dict with sentiment scores
"""
pass
```
</Accordion>
</AccordionGroup>
</Card>
</CardGroup>
<br />
<CardGroup cols={1}>
<Card title="Performance Optimization" icon="bolt" iconType="solid">
<AccordionGroup>
<Accordion title="Efficient Processing">
Optimize resource usage and processing time.
```python
# Use generators for large datasets
def process_large_data():
for chunk in data_generator():
yield process_chunk(chunk)
```
</Accordion>
<Accordion title="Resource Management">
Properly handle resource allocation and cleanup.
```python
async with aiohttp.ClientSession() as session:
# Resource automatically managed
await process_data(session)
```
</Accordion>
<Accordion title="Caching">
Implement caching for frequently accessed data.
```python
@cache.memoize(timeout=300)
def expensive_operation(data: str) -> Dict:
return process_expensive(data)
```
</Accordion>
<Accordion title="Async Operations">
Use async/await for I/O-bound operations.
```python
async def fetch_data(urls: List[str]):
async with aiohttp.ClientSession() as session:
tasks = [fetch_url(session, url) for url in urls]
return await asyncio.gather(*tasks)
```
</Accordion>
</AccordionGroup>
</Card>
</CardGroup>
<br />
<CardGroup cols={1}>
<Card title="Security Best Practices" icon="shield-check" iconType="solid">
<AccordionGroup>
<Accordion title="Input Validation">
Always validate and sanitize inputs to prevent security vulnerabilities.
```python
def process_user_input(data: str) -> str:
if not isinstance(data, str):
raise ValueError("Input must be string")
return sanitize_input(data.strip())
```
</Accordion>
<Accordion title="Rate Limiting">
Implement rate limiting for API calls to prevent abuse.
```python
@rate_limit(calls=100, period=60)
async def api_call():
return await make_request()
```
</Accordion>
<Accordion title="API Key Management">
Securely handle API keys and credentials using environment variables.
```python
# Use environment variables
api_key = os.getenv('API_KEY')
if not api_key:
raise ConfigError("API key not found")
```
</Accordion>
<Accordion title="Error Masking">
Hide sensitive information in error messages to prevent information leakage.
```python
try:
result = process_sensitive_data()
except Exception as e:
# Log detailed error internally
logger.error(f"Detailed error: {str(e)}")
# Return sanitized error to user
raise PublicError("Processing failed")
```
</Accordion>
</AccordionGroup>
</Card>
</CardGroup>
<br />
<Tip>
**Pro Tip**: Start with these practices from the beginning of your project. It's easier to maintain good practices than to retrofit them later.
</Tip>
@@ -0,0 +1,333 @@
---
title: "Code Analysis Agent UI"
sidebarTitle: "Code Analysis"
description: "Build an interactive web interface for analyzing code quality and providing detailed recommendations using Streamlit and AI agents."
icon: "laptop-code"
---
```mermaid
flowchart LR
Input[Input URL] --> Process[Process Code]
Process --> Analyze[AI Analysis]
Analyze --> Display[Display Results]
Display --> Metrics[Show Metrics]
Display --> Details[Show Details]
style Input fill:#8B0000,color:#fff
style Process fill:#2E8B57,color:#fff
style Analyze fill:#2E8B57,color:#fff
style Display fill:#2E8B57,color:#fff
style Metrics fill:#2E8B57,color:#fff
style Details fill:#2E8B57,color:#fff
```
## What is the Code Analysis Streamlit App?
The Code Analysis Streamlit App provides a user-friendly web interface for analyzing code repositories and generating comprehensive quality assessments. It combines AI-powered code analysis with an interactive dashboard to display detailed metrics, recommendations, and insights.
## Features
<CardGroup cols={2}>
<Card title="Repository Analysis" icon="code-branch">
Support for GitHub URLs and local code repositories.
</Card>
<Card title="Real-time Processing" icon="spinner">
Live analysis and evaluation of code.
</Card>
<Card title="Interactive Metrics" icon="chart-column">
Visual presentation of code quality metrics.
</Card>
<Card title="Detailed Reports" icon="file-lines">
Comprehensive analysis of code structure and patterns.
</Card>
<Card title="Best Practices" icon="check-double">
Evaluation against industry best practices.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Dependencies">
Install the required packages:
```bash
pip install streamlit praisonaiagents gitingest
```
</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 the App">
Create a new file `code_analysis_app.py` with the following code:
```python
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict, Any
from gitingest import ingest
# Import the same classes and code from code-analysis-agents.py
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Create code analyzer agent
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
# Create analysis task
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
result = agents.start(context_text)
# Extract the Pydantic model from the result
if isinstance(result, dict) and 'task_results' in result:
# Get the first task result's pydantic output
analysis_result = result['task_results'][0].pydantic
if isinstance(analysis_result, CodeAnalysisReport):
return analysis_result
# If we can't get the Pydantic model, create one from the raw data
return CodeAnalysisReport(**result)
def display_code_metrics(metrics, cols):
"""Display code metrics in columns with color-coded scores"""
for i, metric in enumerate(metrics):
score = metric.score
color = "red" if score < 60 else "orange" if score < 75 else "green"
# Use modulo to alternate between columns
with cols[i % len(cols)]:
st.markdown(f"### {metric.category}")
st.markdown(f"**Score:** :{color}[{score}%]")
for finding in metric.findings:
st.markdown(f"• {finding}")
def display_section(title: str, items: list, icon: str = "•"):
"""Display a section with items in a consistent format"""
st.markdown(f"### {title}")
for item in items:
if isinstance(item, dict):
for key, value in item.items():
st.markdown(f"{icon} **{key}**: {value}")
else:
st.markdown(f"{icon} {item}")
def main():
st.set_page_config(
page_title="Code Analysis Agent",
layout="wide",
initial_sidebar_state="expanded"
)
st.title("Code Analysis Agent")
with st.sidebar:
st.header("Input")
code_source = st.text_input(
"GitHub URL or Local Path",
placeholder="https://github.com/username/repo or /path/to/directory"
)
analyze_button = st.button("Analyze Code", type="primary")
if analyze_button and code_source:
try:
with st.spinner("Analyzing code..."):
result = analyze_code(code_source)
# Overall Metrics
st.header("Overall Metrics")
cols = st.columns(6)
metrics = {
"Overall Quality": result.overall_quality,
"Architecture": result.architecture_score,
"Maintainability": result.maintainability_score,
"Performance": result.performance_score,
"Security": result.security_score,
"Test Coverage": result.test_coverage
}
for (metric, value), col in zip(metrics.items(), cols):
color = "red" if value < 60 else "orange" if value < 75 else "green"
col.metric(metric, f"{value}%")
col.markdown(f":{color}[{'●' * (value // 20)}]")
# Detailed Analysis
st.header("Detailed Analysis")
metric_cols = st.columns(2)
display_code_metrics(result.code_metrics, metric_cols)
# Technology Stack
col1, col2 = st.columns(2)
with col1:
st.header("Technology Stack")
for tech in result.tech_stack:
st.markdown(f"🔧 {tech}")
with col2:
st.header("Complexity Metrics")
for metric, value in result.complexity_metrics.items():
st.metric(metric.replace('_', ' ').title(), value)
# Key Findings
st.header("Key Findings")
cols = st.columns(2)
with cols[0]:
display_section("✅ Strengths", result.key_strengths)
display_section("🔄 Best Practices", result.best_practices)
with cols[1]:
display_section("⚠️ Areas for Improvement", result.improvement_areas)
display_section("❗ Potential Risks", result.potential_risks)
# Recommendations
st.header("Recommendations")
for i, rec in enumerate(result.recommendations, 1):
st.markdown(f"**{i}.** {rec}")
# Documentation Quality
st.header("Documentation")
doc_score = result.documentation_quality
color = "red" if doc_score < 60 else "orange" if doc_score < 75 else "green"
st.markdown(f"Documentation Quality: :{color}[{doc_score}%]")
except Exception as e:
st.error(f"Error analyzing code: {str(e)}")
st.exception(e)
elif analyze_button:
st.warning("Please enter a GitHub URL or local path")
if __name__ == "__main__":
main()
```
</Step>
<Step title="Run the App">
Start the Streamlit app:
```bash
streamlit run code_analysis_app.py
```
</Step>
</Steps>
## Understanding the Interface
The Streamlit app provides an intuitive interface with the following sections:
- **Input**: GitHub URL or local path input in the sidebar
- **Overall Metrics**: Visual display of key quality scores
- Overall Quality
- Architecture Score
- Maintainability Score
- Performance Score
- Security Score
- Test Coverage
- **Detailed Analysis**:
- Code Metrics with Findings
- Technology Stack Overview
- Complexity Metrics
- **Key Findings**:
- Strengths
- Best Practices
- Areas for Improvement
- Potential Risks
- **Additional Information**:
- Recommendations
- Documentation Quality Assessment
## Next Steps
<CardGroup>
<Card title="Streamlit Docs" icon="book" href="https://docs.streamlit.io">
Learn more about Streamlit features
</Card>
<Card title="PraisonAI Docs" icon="bolt" href="/introduction">
Explore PraisonAI capabilities
</Card>
<Card title="Examples" icon="code" href="/examples">
View more example applications
</Card>
</CardGroup>
+158
View File
@@ -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>
+119
View File
@@ -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,323 @@
---
title: "Hackathon Judge Agent UI"
sidebarTitle: "Hackathon Judge"
description: "Build an interactive web interface for evaluating hackathon projects using Streamlit and AI agents."
icon: "desktop"
---
```mermaid
flowchart LR
Upload[Upload Video] --> Process[Process Video]
Process --> Evaluate[AI Evaluation]
Evaluate --> Display[Display Results]
Display --> Scores[Show Scores]
Display --> Feedback[Show Feedback]
style Upload fill:#8B0000,color:#fff
style Process fill:#2E8B57,color:#fff
style Evaluate fill:#2E8B57,color:#fff
style Display fill:#2E8B57,color:#fff
style Scores fill:#2E8B57,color:#fff
style Feedback fill:#2E8B57,color:#fff
```
## What is the Hackathon Judge Streamlit App?
The Hackathon Judge Streamlit App provides a user-friendly web interface for evaluating hackathon projects through video demonstrations. It combines the power of AI evaluation with an interactive dashboard to display comprehensive project assessments, scores, and feedback.
## Features
<CardGroup cols={2}>
<Card title="Video Upload" icon="upload">
Easy-to-use interface for uploading project demonstration videos.
</Card>
<Card title="Real-time Processing" icon="spinner">
Live processing and evaluation of uploaded videos.
</Card>
<Card title="Interactive Dashboard" icon="chart-simple">
Visual presentation of scores and metrics.
</Card>
<Card title="Detailed Feedback" icon="comments">
Comprehensive display of evaluation results and recommendations.
</Card>
<Card title="Market Analysis" icon="briefcase">
Visual presentation of market potential and scalability.
</Card>
</CardGroup>
## Quick Start
<Steps>
<Step title="Install Dependencies">
Install the required packages:
```bash
pip install streamlit praisonaiagents opencv-python moviepy
```
</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 the App">
Create a new file `hackathon_judge_app.py` with the following code:
```python
import streamlit as st
import os
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import tempfile
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Set page config
st.set_page_config(
page_title="Hackathon Project Evaluator",
page_icon="🏆",
layout="wide"
)
# Create Vision Analysis Agent
@st.cache_resource
def get_hackathon_judge():
return Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
hackathon_judge = get_hackathon_judge()
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
elif isinstance(response, str):
evaluation_data = json.loads(response)
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
# Title and description
st.title("🏆 Hackathon Judge Agent")
st.markdown("""
Upload your hackathon project demonstration video for an AI-powered evaluation.
Get comprehensive feedback on various aspects of your project.
""")
# File uploader
uploaded_file = st.file_uploader("Choose a video file", type=['mp4', 'avi', 'mov', 'mkv'])
if uploaded_file:
# Create a temporary file to store the video
with tempfile.NamedTemporaryFile(delete=False, suffix='.'+uploaded_file.name.split('.')[-1]) as tmp_file:
tmp_file.write(uploaded_file.getvalue())
video_path = tmp_file.name
with st.spinner("🤖 AI is evaluating your project..."):
try:
# Evaluate the project
result = evaluate_project(video_path)
# Display results
st.header("Overall Score")
st.metric("Overall Score", f"{result.overall_score}/100")
# Display detailed scores
st.header("Detailed Scores")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Innovation", f"{result.innovation_score}/100")
st.metric("Technical Complexity", f"{result.technical_complexity}/100")
with col2:
st.metric("Presentation", f"{result.presentation_quality}/100")
st.metric("User Experience", f"{result.user_experience}/100")
with col3:
st.metric("Completeness", f"{result.completeness}/100")
# Display qualitative feedback
st.header("Key Strengths")
for strength in result.key_strengths:
st.write(f"• {strength}")
st.header("Areas for Improvement")
for area in result.areas_for_improvement:
st.write(f"• {area}")
st.header("Technical Highlights")
for highlight in result.technical_highlights:
st.write(f"• {highlight}")
st.header("Notable Features")
for feature in result.notable_features:
st.write(f"• {feature}")
st.header("Recommendations")
for rec in result.recommendations:
st.write(f"• {rec}")
# Market Analysis
st.header("Market Analysis")
col1, col2 = st.columns(2)
with col1:
st.subheader("Market Potential")
st.write(result.market_potential)
with col2:
st.subheader("Scalability Assessment")
st.write(result.scalability_assessment)
except Exception as e:
st.error(f"Error evaluating the project: {str(e)}")
finally:
# Clean up the temporary file
os.unlink(video_path)
else:
# Display placeholder content
st.info("👆 Upload a video file to get started!")
```
</Step>
<Step title="Run the App">
Start the Streamlit app:
```bash
streamlit run hackathon_judge_app.py
```
</Step>
</Steps>
## Understanding the Interface
The Streamlit app provides an intuitive interface with the following sections:
- **Video Upload**: Drag and drop or browse to upload your project demo video
- **Overall Score**: A prominent display of the project's overall rating
- **Detailed Scores**:
- Innovation Score
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
- **Qualitative Feedback**:
- Key Strengths
- Areas for Improvement
- Technical Highlights
- Notable Features
- Recommendations
- **Market Analysis**:
- Market Potential
- Scalability Assessment
## Next Steps
<CardGroup>
<Card title="Streamlit Docs" icon="book" href="https://docs.streamlit.io">
Learn more about Streamlit features
</Card>
<Card title="PraisonAI Docs" icon="bolt" href="/introduction">
Explore PraisonAI capabilities
</Card>
<Card title="Examples" icon="code" href="/examples">
View more example applications
</Card>
</CardGroup>
+158
View File
@@ -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>
+1 -1
View File
@@ -4,7 +4,7 @@ config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "custom_knowledge",
"collection_name": "praison",
"path": ".praison",
}
}
+39
View File
@@ -0,0 +1,39 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Define the configuration for the Knowledge instance
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
}
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="gpt-4o-mini"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
+22
View File
@@ -0,0 +1,22 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
agent = Agent(
instructions="You are a loop agent that creating a loop of tasks.",
llm="gpt-4o-mini"
)
task = Task(
description="Create the list of tasks to be looped through.",
agent=agent,
task_type="loop",
input_file="tasks.csv"
)
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
process="workflow",
max_iter=30
)
agents.start()
Binary file not shown.
@@ -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
Loaded 100 of 127 files, more files were not shown because too many files have changed in this diff. Show more