Compare commits

...
31 Commits
Author SHA1 Message Date
Mervin Praison 3f2cd51d4b Merge pull request #41 from MervinPraison/develop
v0.0.21 final
2024-06-10 16:56:46 +01:00
Mervin Praison 111343cb1d Merge pull request #39 from MervinPraison/feature/PRAISON-1-add-tools
Docs
2024-06-10 16:56:02 +01:00
Mervin Praison ce38f08ec0 Merge pull request #40 from MervinPraison/develop
v0.0.21
2024-06-10 16:55:05 +01:00
MervinPraison 3984768406 Adding Other Tools 2024-06-10 15:54:27 +01:00
Mervin Praison 8533065061 Merge pull request #37 from south-american-cowboy/mit-license-proposal
MIT License proposal
2024-06-03 15:08:25 +01:00
South American Cowboy 1ca5737951 MIT License Proposal 2024-05-30 05:33:30 -04:00
MervinPraison d216393140 v0.0.21 2024-05-14 08:20:46 +01:00
Mervin Praison 3d2f5cdc9e Merge pull request #34 from MervinPraison/feature/PRAISON-1-add-tools
Updating readme
2024-05-09 11:53:09 +01:00
MervinPraison aa50d69690 Updating readme 2024-05-09 11:52:42 +01:00
Mervin Praison 1ccaac0794 Merge pull request #33 from MervinPraison/feature/PRAISON-1-add-tools
Updating readme
2024-05-09 11:41:58 +01:00
MervinPraison 7371dc15ab Updating readme 2024-05-09 11:41:29 +01:00
Mervin Praison 9e760a21a1 Merge pull request #32 from MervinPraison/feature/PRAISON-1-add-tools
Updating readme
2024-05-09 11:37:45 +01:00
MervinPraison 7248b1ab0a Updating readme' 2024-05-09 11:37:24 +01:00
Mervin Praison c35a4e973a Merge pull request #30 from MervinPraison/develop
v0.0.20 Release
2024-05-06 21:12:23 +01:00
Mervin Praison 89db863fd0 Merge pull request #29 from MervinPraison/feature/PRAISON-1-add-tools
v0.0.19 fixes 2
2024-05-06 21:10:35 +01:00
Mervin Praison 6bf1fa6c61 Merge pull request #28 from austingreisman/patch-1
Update requirements.txt - praisonai pip install broken
2024-05-06 21:09:45 +01:00
Austin Greisman 27a4597c37 Update requirements.txt
required to run the example file in current version of development branch
2024-05-05 15:42:58 -04:00
MervinPraison 0a27c9f64c v0.0.19 fixes 2 2024-05-03 14:31:47 +01:00
Mervin Praison 932afad679 Merge pull request #27 from MervinPraison/feature/PRAISON-1-add-tools
Feature/praison 1 add tools
2024-05-03 14:18:06 +01:00
MervinPraison 4ddd0bc5a9 v0.0.19 fixes 2024-05-03 14:16:17 +01:00
MervinPraison d814aa66eb v0.0.19 2024-05-03 13:48:43 +01:00
MervinPraison f2d76d2d56 adding custom tool with basetool 2024-05-03 13:29:49 +01:00
Mervin Praison af88f121e3 Merge pull request #26 from MervinPraison/feature/PRAISON-1-add-tools
Feature/praison 1 add tools
2024-05-03 01:12:46 +01:00
MervinPraison b21d48c51d adding custom tools working 2024-05-03 01:07:53 +01:00
MervinPraison ba2dfe1909 adding internet search tool testg 2024-05-03 00:58:39 +01:00
Mervin Praison 865aa65448 Merge pull request #22 from cypheroxide/patch-1
Update switch_llm_provider.sh
2024-04-25 22:14:55 +01:00
Angel Santiago e5ceca314d Update switch_llm_provider.sh
Add support for Ollama local model configuration

This commit extends the existing platform selection script to include support for Ollama local models. The new branch in the conditional logic handles the 'ollama' argument to configure the environment for accessing models served locally. Key changes include:

- Addition of an `elif` clause for 'ollama' to set up the model name, API base URL, and API key.
- Setup for using an SSH public key for secure connections, formatted in 'ssh-ed25519'.
- Default model naming fallback similar to existing platform configurations.
- Confirmation message to indicate successful initialization of the Ollama configuration.

This update enables the script to interact with locally hosted Ollama models, enhancing its versatility and utility in development environments that utilize different model serving platforms.
2024-04-16 21:48:24 -05:00
MervinPraison 2dacd09724 adding custom tool but autogen yet to be fixed 2024-04-10 12:32:00 +05:30
MervinPraison b92f6e0bb3 adding custom tool 2024-04-10 08:20:38 +05:30
MervinPraison 2c74084eaf adding custom tool settings 2024-04-08 12:38:33 +05:30
Mervin Praison 3a0cb0e33a Merge pull request #15 from MervinPraison/develop
v0.0.18
2024-04-02 23:01:35 +05:30
48 changed files with 1981 additions and 1650 deletions

No files matched your search

+18 -1
View File
@@ -13,4 +13,21 @@ assets/*
praisonAI.egg-info
flagged
test.yaml
db
db
praisonai_prompt.txt
watch.sh
docs.sh
# Ignore Sphinx build directory
docs/_build/
docs/source/
docs/build/
# Ignore Sphinx cache
docs/_build/doctrees/
docs/_build/doctrees/*
docs/_build/doctrees/.doctrees
# Ignore Sphinx logs and local build files
docs/_build/.buildinfo
docs/_build/.buildinfo/*
docs/_build/.buildinfo/.buildinfo
+35
View File
@@ -0,0 +1,35 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.12"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
# fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
# python:
# install:
# - requirements: docs/requirements.txt
+1 -1
View File
@@ -1,6 +1,6 @@
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install flask praisonai==0.0.18 gunicorn markdown
RUN pip install flask praisonai==0.0.21 gunicorn markdown
EXPOSE 8080
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
+20
View File
@@ -0,0 +1,20 @@
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+86 -5
View File
@@ -2,6 +2,14 @@
Praison AI, leveraging both AutoGen and CrewAI or any other agent framework, represents a low-code, centralised framework designed to simplify the creation and orchestration of multi-agent systems for various LLM applications, emphasizing ease of use, customization, and human-agent interaction.
## TL;DR
```bash
pip install praisonai
export OPENAI_API_KEY="Enter your API key"
praisonai --init create a movie script about dog in moon
praisonai
```
## Installation
```bash
@@ -9,13 +17,21 @@ 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 initialse with a specific agent framework:
### To initialse with a specific agent framework (Optional):
```bash
praisonai --framework autogen --init create movie script about cat in mars
@@ -33,7 +49,7 @@ or
python -m praisonai
```
### Specify the agent framework
### Specify the agent framework (Optional):
```bash
praisonai --framework autogen
@@ -45,6 +61,68 @@ praisonai --framework autogen
praisonai --auto create a movie script about Dog in Moon
```
## Create Custom Tools
### TL;DR to Create a Custom Tool
```bash
pip install praisonai duckduckgo-search
export OPENAI_API_KEY="Enter your API key"
praisonai --init research about the latest AI News and prepare a detailed report
```
- Add `- InternetSearchTool` in the agents.yaml file in the tools section.
- Create a file called tools.py and add this code [tools.py](./tools.py)
```bash
praisonai
```
### Pre-requisite to Create a Custom Tool
`agents.yaml` file should be present in the current directory.
If it doesn't exist, create it by running the command `praisonai --init research about the latest AI News and prepare a detailed report`.
### Step 1 to Create a Custom Tool
Create a file called tools.py in the same directory as the agents.yaml file.
```python
# 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
```
### Step 2 to Create a Custom Tool
Add the tool to the agents.yaml file as show below under the tools section `- InternetSearchTool`.
```yaml
framework: crewai
topic: research about the latest AI News and prepare a detailed report
roles:
research_analyst:
backstory: Experienced in gathering and analyzing data related to AI news trends.
goal: Analyze AI News trends
role: Research Analyst
tasks:
gather_data:
description: Conduct in-depth research on the latest AI News trends from reputable
sources.
expected_output: Comprehensive report on current AI News trends.
tools:
- InternetSearchTool
```
## Test
```bash
@@ -53,7 +131,7 @@ python -m unittest tests.test
## Agents Playbook
### Simple Playbook
### Simple Playbook Example
```yaml
framework: crewai
@@ -69,7 +147,7 @@ roles:
expected_output: 'Complete script ready for production.'
```
### Detailed Playbook
### Detailed Playbook Example
```yaml
framework: crewai
@@ -169,9 +247,11 @@ gcloud run deploy praisonai-service \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars OPENAI_MODEL_NAME=${OPENAI_MODEL_NAME},OPENAI_API_KEY=${OPENAI_API_KEY},OPENAI_API_BASE=${OPENAI_API_BASE}
```
## Other Models
```bash
Ollama
OPENAI_API_BASE='http://localhost:11434/v1'
OPENAI_MODEL_NAME='mistral'
@@ -191,6 +271,7 @@ Mistral API¶
OPENAI_API_BASE=https://api.mistral.ai/v1
OPENAI_MODEL_NAME="mistral-small"
OPENAI_API_KEY=your-mistral-api-key
```
## Contributing
@@ -200,4 +281,4 @@ OPENAI_API_KEY=your-mistral-api-key
- Make changes and commit: `git commit -am "Add some feature"`
- Push to your fork: `git push origin new-feature`
- Submit a pull request via GitHub's web interface.
- Await feedback from project maintainers.
- Await feedback from project maintainers.
+42
View File
@@ -0,0 +1,42 @@
framework: crewai
topic: create a movie about cat in mars based on https://blog.celtx.com/how-to-write-a-good-story/
roles:
story_developer:
backstory: Experienced in crafting compelling narratives for a diverse audience.
goal: Develop an engaging storyline for a movie about cats in Mars
role: Story Developer
tasks:
storyline_creation:
description: Create a captivating storyline for a movie about cats in Mars
inspired by the blog post at https://blog.celtx.com/how-to-write-a-good-story/
expected_output: Detailed storyline with key plot points, character motivations,
and setting descriptions.
tools:
- 'ScrapeWebsiteTool'
screenwriter:
backstory: Proficient in translating complex narratives into engaging screenplay
format.
goal: Transform the storyline into a script
role: Screenwriter
tasks:
script_creation:
description: Transform the developed storyline into a script for the movie
about cats in Mars.
expected_output: Complete script with dialogues, scenes, and stage directions
ready for production.
tools:
- ''
director:
backstory: Experienced in visual storytelling and bringing scripts to life on
screen.
goal: Oversee the production of the movie
role: Director
tasks:
movie_production:
description: Take the script and lead the team to produce the movie 'Cats
in Mars' based on the provided content and script.
expected_output: Completed movie ready for distribution with compelling visuals
and engaging storytelling.
tools:
- ''
dependencies: []
+28 -31
View File
@@ -1,42 +1,39 @@
framework: crewai
topic: create a movie about cat in mars based on https://blog.celtx.com/how-to-write-a-good-story/
topic: research about the causes of lung disease
roles:
story_developer:
backstory: Experienced in crafting compelling narratives for a diverse audience.
goal: Develop an engaging storyline for a movie about cats in Mars
role: Story Developer
research_analyst:
backstory: Experienced in analyzing scientific data related to respiratory health.
goal: Analyze data on lung diseases
role: Research Analyst
tasks:
storyline_creation:
description: Create a captivating storyline for a movie about cats in Mars
inspired by the blog post at https://blog.celtx.com/how-to-write-a-good-story/
expected_output: Detailed storyline with key plot points, character motivations,
and setting descriptions.
data_analysis:
description: Gather and analyze data on the causes and risk factors of lung
diseases.
expected_output: Report detailing key findings on lung disease causes.
tools:
- 'ScrapeWebsiteTool'
screenwriter:
backstory: Proficient in translating complex narratives into engaging screenplay
format.
goal: Transform the storyline into a script
role: Screenwriter
- 'PubmedQueryRun'
medical_writer:
backstory: Skilled in translating complex medical information into accessible
content.
goal: Compile comprehensive content on lung disease causes
role: Medical Writer
tasks:
script_creation:
description: Transform the developed storyline into a script for the movie
about cats in Mars.
expected_output: Complete script with dialogues, scenes, and stage directions
ready for production.
content_creation:
description: Create detailed content summarizing the research findings on
lung disease causes.
expected_output: Document outlining various causes and risk factors of lung
diseases.
tools:
- ''
director:
backstory: Experienced in visual storytelling and bringing scripts to life on
screen.
goal: Oversee the production of the movie
role: Director
editor:
backstory: Proficient in editing medical content for accuracy and clarity.
goal: Review and refine content on lung disease causes
role: Editor
tasks:
movie_production:
description: Take the script and lead the team to produce the movie 'Cats
in Mars' based on the provided content and script.
expected_output: Completed movie ready for distribution with compelling visuals
and engaging storytelling.
content_review:
description: Edit and refine the compiled content on lung disease causes for
accuracy and coherence.
expected_output: Finalized document on lung disease causes ready for dissemination.
tools:
- ''
dependencies: []
+42
View File
@@ -0,0 +1,42 @@
framework: crewai
topic: create a movie about cat in mars based on https://www.grammarly.com/blog/how-to-write-a-story/
roles:
story_developer:
backstory: Experienced in crafting compelling narratives for a diverse audience.
goal: Develop an engaging storyline for a movie about cats in Mars
role: Story Developer
tasks:
storyline_creation:
description: Create a captivating storyline for a movie about cats in Mars
inspired by the blog post at https://www.grammarly.com/blog/how-to-write-a-story/
expected_output: Detailed storyline with key plot points, character motivations,
and setting descriptions.
tools:
- 'ScrapeWebsiteTool'
screenwriter:
backstory: Proficient in translating complex narratives into engaging screenplay
format.
goal: Transform the storyline into a script
role: Screenwriter
tasks:
script_creation:
description: Transform the developed storyline into a script for the movie
about cats in Mars.
expected_output: Complete script with dialogues, scenes, and stage directions
ready for production.
tools:
- ''
director:
backstory: Experienced in visual storytelling and bringing scripts to life on
screen.
goal: Oversee the production of the movie
role: Director
tasks:
movie_production:
description: Take the script and lead the team to produce the movie 'Cats
in Mars' based on the provided content and script.
expected_output: Completed movie ready for distribution with compelling visuals
and engaging storytelling.
tools:
- ''
dependencies: []
+43
View File
@@ -0,0 +1,43 @@
framework: crewai
topic: research about nvidia growth
roles:
data_collector:
backstory: An experienced researcher with the ability to efficiently collect and
organize vast amounts of data.
goal: Gather information on Nvidia's growth
role: Data Collector
tasks:
data_collection_task:
description: Collect data on Nvidia's growth from various sources such as
financial reports, news articles, and company announcements.
expected_output: A comprehensive document detailing data points on Nvidia's
growth over the years.
tools:
- 'YouSearchTool'
data_analyst:
backstory: Specializes in extracting insights from large datasets, proficient
in quantitative and qualitative analysis.
goal: Analyze the collected data to identify trends and patterns
role: Data Analyst
tasks:
data_analysis_task:
description: Analyze the collected data to identify key trends and patterns
in Nvidia's growth.
expected_output: An analytical report summarizing trends, patterns, and key
growth metrics of Nvidia.
tools:
- ''
report_preparer:
backstory: Experienced in creating detailed reports and presentations, turning
analytical data into actionable insights.
goal: Generate a final report on Nvidia's growth
role: Report Preparer
tasks:
report_preparation_task:
description: Create a detailed report based on the analysis, highlighting
Nvidia's growth trajectory.
expected_output: A polished, comprehensive report summarizing Nvidia's growth
with visual aids and key insights.
tools:
- ''
dependencies: []
@@ -0,0 +1,26 @@
framework: crewai
topic: research about the latest AI News and prepare a detailed report
roles:
research_analyst:
backstory: Experienced in gathering and analyzing data related to AI news trends.
goal: Analyze AI News trends
role: Research Analyst
tasks:
gather_data:
description: Conduct in-depth research on the latest AI News trends from reputable
sources.
expected_output: Comprehensive report on current AI News trends.
tools:
- 'InternetSearchTool'
content_creator:
backstory: Skilled in writing informative and engaging content about AI News.
goal: Create detailed reports on AI News
role: Content Creator
tasks:
compile_report:
description: Compile all gathered data into a detailed report with analysis
and insights.
expected_output: Well-structured report on the latest AI News with key insights.
tools:
- ''
dependencies: []
@@ -0,0 +1,39 @@
framework: crewai
topic: research about the causes of lung disease
roles:
research_analyst:
backstory: Experienced in analyzing scientific data related to respiratory health.
goal: Analyze data on lung diseases
role: Research Analyst
tasks:
data_analysis:
description: Gather and analyze data on the causes and risk factors of lung
diseases.
expected_output: Report detailing key findings on lung disease causes.
tools:
- 'PubmedQueryRun'
medical_writer:
backstory: Skilled in translating complex medical information into accessible
content.
goal: Compile comprehensive content on lung disease causes
role: Medical Writer
tasks:
content_creation:
description: Create detailed content summarizing the research findings on
lung disease causes.
expected_output: Document outlining various causes and risk factors of lung
diseases.
tools:
- ''
editor:
backstory: Proficient in editing medical content for accuracy and clarity.
goal: Review and refine content on lung disease causes
role: Editor
tasks:
content_review:
description: Edit and refine the compiled content on lung disease causes for
accuracy and coherence.
expected_output: Finalized document on lung disease causes ready for dissemination.
tools:
- ''
dependencies: []
+20
View File
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+28
View File
@@ -0,0 +1,28 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'PraisonAI'
copyright = '2024, Mervin Praison'
author = 'Mervin Praison'
release = '0.0.21'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx_rtd_theme']
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'alabaster'
html_static_path = ['_static']
+20
View File
@@ -0,0 +1,20 @@
.. PraisonAI documentation master file, created by
sphinx-quickstart on Mon Jun 10 12:11:57 2024.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to PraisonAI's documentation!
=====================================
.. toctree::
:maxdepth: 2
:caption: Contents:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+35
View File
@@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd
+49
View File
@@ -0,0 +1,49 @@
# 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
from langchain_community.tools.pubmed.tool import PubmedQueryRun
from langchain_community.tools.reddit_search.tool import RedditSearchRun
# pip install tavily-python
from langchain_community.utilities.tavily_search import TavilySearchAPIWrapper
from langchain_community.utilities.you import YouSearchAPIWrapper
# pip install youtube_search
from langchain_community.tools import YouTubeSearchTool
# pip install wikipedia
from langchain_community.utilities import WikipediaAPIWrapper
class TavilyTool(BaseTool):
name: str = "TavilyTool"
description: str = "Search Tavily for relevant information based on a query."
def _run(self, query: str):
api_wrapper = TavilySearchAPIWrapper()
results = api_wrapper.results(query=query, max_results=5)
return results
class YouSearchTool(BaseTool):
name: str = "You Search Tool"
description: str = "Search You.com for relevant information based on a query."
def _run(self, query: str):
api_wrapper = YouSearchAPIWrapper()
results = api_wrapper.results(query=query, max_results=5)
return results
class WikipediaSearchTool(BaseTool):
name: str = "WikipediaSearchTool"
description: str = "Search Wikipedia for relevant information based on a query."
def _run(self, query: str):
api_wrapper = WikipediaAPIWrapper(top_k_results=4, doc_content_chars_max=100)
results = api_wrapper.load(query=query)
return results
Generated
+955 -933
View File
File diff suppressed because it is too large. Load diff
+57 -96
View File
@@ -1,4 +1,4 @@
# agents_generator.py
# praisonai/agents_generator.py
import sys
from .version import __version__
@@ -11,14 +11,49 @@ import autogen
import gradio as gr
import argparse
from .auto import AutoGenerator
from crewai_tools import *
from .tools import *
from crewai_tools import (
CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, DirectoryReadTool,
FileReadTool, TXTSearchTool, JSONSearchTool, MDXSearchTool, PDFSearchTool, RagTool,
ScrapeElementFromWebsiteTool, ScrapeWebsiteTool, WebsiteSearchTool, XMLSearchTool, YoutubeChannelSearchTool,
YoutubeVideoSearchTool
)
from .inbuilt_tools import *
import inspect
from pathlib import Path
import importlib
import importlib.util
from praisonai_tools import BaseTool
class AgentsGenerator:
def __init__(self, agent_file, framework, config_list):
self.agent_file = agent_file
self.framework = framework
self.config_list = config_list
def is_function_or_decorated(self, obj):
return inspect.isfunction(obj) or hasattr(obj, '__call__')
def load_tools_from_module(self, module_path):
spec = importlib.util.spec_from_file_location("tools_module", module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return {name: obj for name, obj in inspect.getmembers(module, self.is_function_or_decorated)}
def load_tools_from_module_class(self, module_path):
spec = importlib.util.spec_from_file_location("tools_module", module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return {name: obj() for name, obj in inspect.getmembers(module, lambda x: inspect.isclass(x) and (x.__module__.startswith('langchain_community.tools') or issubclass(x, BaseTool)) and x is not BaseTool)}
def load_tools_from_package(self, package_path):
tools_dict = {}
for module_file in os.listdir(package_path):
if module_file.endswith('.py') and not module_file.startswith('__'):
module_name = f"{package_path.name}.{module_file[:-3]}" # Remove .py for import
module = importlib.import_module(module_name)
for name, obj in inspect.getmembers(module, self.is_function_or_decorated):
tools_dict[name] = obj
return tools_dict
def generate_crew_and_kickoff(self):
if self.agent_file == '/app/api:app' or self.agent_file == 'api:app':
@@ -51,9 +86,19 @@ class AgentsGenerator:
'WebsiteSearchTool': WebsiteSearchTool(),
'XMLSearchTool': XMLSearchTool(),
'YoutubeChannelSearchTool': YoutubeChannelSearchTool(),
'YoutubeVideoSearchTool': YoutubeVideoSearchTool()
'YoutubeVideoSearchTool': YoutubeVideoSearchTool(),
}
# config['tools'] = [tools_dict[tool] for tool in config.get('tools', []) if tool in tools_dict]
root_directory = os.getcwd()
tools_py_path = os.path.join(root_directory, 'tools.py')
tools_dir_path = Path(root_directory) / 'tools'
if os.path.isfile(tools_py_path):
tools_dict.update(self.load_tools_from_module_class(tools_py_path))
# print("tools.py exists in the root directory. Loading tools.py and skipping tools folder.")
elif tools_dir_path.is_dir():
tools_dict.update(self.load_tools_from_module_class(tools_dir_path))
# print("tools folder exists in the root directory")
framework = self.framework or config.get('framework')
agents = {}
@@ -86,7 +131,12 @@ class AgentsGenerator:
)
for tool in details.get('tools', []):
if tool in tools_dict:
tool_class = globals()[f'autogen_{type(tools_dict[tool]).__name__}']
try:
tool_class = globals()[f'autogen_{type(tools_dict[tool]).__name__}']
print(f"Found {tool_class.__name__} for {tool}")
except KeyError:
print(f"Warning: autogen_{type(tools_dict[tool]).__name__} function not found. Skipping this tool.")
continue
tool_class(agents[role], user_proxy)
# Preparing tasks for initiate_chats
@@ -121,7 +171,6 @@ class AgentsGenerator:
task = Task(description=description_filled, expected_output=expected_output_filled, agent=agent)
tasks.append(task)
# print(agents)
crew = Crew(
agents=list(agents.values()),
tasks=tasks,
@@ -130,92 +179,4 @@ class AgentsGenerator:
response = crew.kickoff()
result = f"### Task Output ###\n{response}"
return result
# # AutoGen Tools example below
# from typing import Any, Optional
# import os
# from autogen import ConversableAgent
# from autogen_tools import autogen_ScrapeWebsiteTool
# assistant = ConversableAgent(
# name="Assistant",
# system_message="You are a helpful AI assistant. "
# "You can help with website scraping. "
# "Return 'TERMINATE' when the task is done.",
# llm_config={"config_list": [{"model": "gpt-3.5-turbo", "api_key": os.environ["OPENAI_API_KEY"]}]},
# )
# user_proxy = ConversableAgent(
# name="User",
# llm_config=False,
# is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"],
# human_input_mode="NEVER",
# )
# autogen_ScrapeWebsiteTool(assistant, user_proxy)
# chat_result = user_proxy.initiate_chat(assistant, message="Scrape the official Nodejs website.")
# # CrewAI Tools example below
# import os
# from crewai import Agent, Task, Crew
# # Importing crewAI tools
# from crewai_tools import (
# DirectoryReadTool,
# FileReadTool,
# SerperDevTool,
# WebsiteSearchTool
# )
# # Set up API keys
# os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key
# os.environ["OPENAI_API_KEY"] = "Your Key"
# # Instantiate tools
# docs_tool = DirectoryReadTool(directory='./blog-posts')
# file_tool = FileReadTool()
# search_tool = SerperDevTool()
# web_rag_tool = WebsiteSearchTool()
# # Create agents
# researcher = Agent(
# role='Market Research Analyst',
# goal='Provide up-to-date market analysis of the AI industry',
# backstory='An expert analyst with a keen eye for market trends.',
# tools=[search_tool, web_rag_tool],
# verbose=True
# )
# writer = Agent(
# role='Content Writer',
# goal='Craft engaging blog posts about the AI industry',
# backstory='A skilled writer with a passion for technology.',
# tools=[docs_tool, file_tool],
# verbose=True
# )
# # Define tasks
# research = Task(
# description='Research the latest trends in the AI industry and provide a summary.',
# expected_output='A summary of the top 3 trending developments in the AI industry with a unique perspective on their significance.',
# agent=researcher
# )
# write = Task(
# description='Write an engaging blog post about the AI industry, based on the research analyst’s summary. Draw inspiration from the latest blog posts in the directory.',
# expected_output='A 4-paragraph blog post formatted in markdown with engaging, informative, and accessible content, avoiding complex jargon.',
# agent=writer,
# output_file='blog-posts/new_post.md' # The final blog post will be saved here
# )
# # Assemble a crew
# crew = Crew(
# agents=[researcher, writer],
# tasks=[research, write],
# verbose=2
# )
# # Execute tasks
# crew.kickoff()
return result
+6 -51
View File
@@ -12,8 +12,7 @@ import gradio as gr
import argparse
from .auto import AutoGenerator
from .agents_generator import AgentsGenerator
from crewai_tools import *
from .tools import *
from .inbuilt_tools import *
class PraisonAI:
def __init__(self, agent_file="agents.yaml", framework="crewai", auto=False, init=False):
@@ -41,21 +40,15 @@ class PraisonAI:
return
invocation_cmd = "praisonai"
version_string = f"PraisonAI version {__version__}"
if args.framework:
self.framework = args.framework
ui = args.ui
if args.agent_file:
if args.agent_file == "tests.test": # Argument used for testing purposes
full_path = os.path.abspath("agents.yaml")
if args.agent_file.startswith("tests.test"): # Argument used for testing purposes
print("test")
else:
full_path = os.path.abspath(args.agent_file)
self.agent_file = full_path
else:
full_path = os.path.abspath(self.agent_file)
self.agent_file = full_path
self.agent_file = args.agent_file
if args.auto or args.init:
temp_topic = ' '.join(args.auto) if args.auto else ' '.join(args.init)
@@ -86,7 +79,7 @@ class PraisonAI:
def parse_args(self):
parser = argparse.ArgumentParser(prog="praisonai", description="praisonAI command-line interface")
parser.add_argument("--framework", choices=["crewai", "autogen"], default="crewai", help="Specify the framework")
parser.add_argument("--framework", choices=["crewai", "autogen"], help="Specify the framework")
parser.add_argument("--ui", action="store_true", help="Enable UI mode")
parser.add_argument("--auto", nargs=argparse.REMAINDER, help="Enable auto mode and pass arguments for it")
parser.add_argument("--init", nargs=argparse.REMAINDER, help="Enable auto mode and pass arguments for it")
@@ -124,41 +117,3 @@ class PraisonAI:
if __name__ == "__main__":
praison_ai = PraisonAI()
praison_ai.main()
## agents.yaml
# framework: autogen
# topic: create movie script about cat in mars
# roles:
# concept_developer:
# backstory: Experienced in creating captivating and original story concepts.
# goal: Generate a unique concept for a movie script about a cat in Mars
# role: Concept Developer
# tools:
# - search_tool
# tasks:
# concept_generation:
# description: Develop a unique and engaging concept for a movie script about
# a cat in Mars.
# expected_output: A detailed concept document for the movie script.
# scriptwriter:
# backstory: Expert in dialogue and script structure, translating concepts into
# scripts.
# goal: Write a script based on the movie concept
# role: Scriptwriter
# tasks:
# scriptwriting_task:
# description: Turn the movie concept into a script, including dialogue and
# scenes.
# expected_output: A production-ready script for the movie about a cat in Mars.
# director:
# backstory: Experienced in visualizing scripts and creating compelling storyboards.
# goal: Create a storyboard and visualize the script
# role: Director
# tasks:
# storyboard_creation:
# description: Create a storyboard for the movie script about a cat in Mars.
# expected_output: A detailed storyboard for the movie about a cat in Mars.
# dependencies: []
+1 -1
View File
@@ -13,7 +13,7 @@ class CloudDeployer:
file.write("FROM python:3.11-slim\n")
file.write("WORKDIR /app\n")
file.write("COPY . .\n")
file.write("RUN pip install flask praisonai==0.0.18 gunicorn markdown\n")
file.write("RUN pip install flask praisonai==0.0.21 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
+2
View File
@@ -0,0 +1,2 @@
# from .base_tool import BaseTool, Tool, tool
from .autogen_tools import *
@@ -1,3 +1,5 @@
# praisonai/inbuilt_tools/autogen_tools.py
from crewai_tools import (
CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, DirectoryReadTool,
FileReadTool, TXTSearchTool, JSONSearchTool, MDXSearchTool, PDFSearchTool, RagTool,
@@ -6,6 +8,60 @@ from crewai_tools import (
)
from typing import Any
from autogen import register_function
import os
import importlib
from pathlib import Path
import os
import inspect
import sys
def create_autogen_tool_function(tool_name):
def autogen_tool(assistant, user_proxy):
def register_tool(tool_class, tool_name, tool_description, assistant, user_proxy):
def tool_func(query: str) -> Any:
tool_instance = tool_class()
return tool_instance.run(query=query)
register_function(tool_func, caller=assistant, executor=user_proxy, name=tool_name, description=tool_description)
root_directory = os.getcwd()
tools_py_path = os.path.join(root_directory, 'tools.py')
tools_dir_path = Path(root_directory) / 'tools'
if os.path.isfile(tools_py_path):
print(f"{tools_py_path} exists in the root directory. Loading {tools_py_path} and skipping tools folder.")
tool_module = importlib.import_module("tools")
elif tools_dir_path.is_dir():
print(f"tools folder exists in the root directory. Loading {tool_name} from tools/{tool_name}.py.")
tool_module = importlib.import_module(f"tools.{tool_name}")
else:
raise ImportError("Neither tools.py nor tools directory found in the root directory.")
Tool = getattr(tool_module, tool_name)
register_tool(Tool, tool_name, f"Description for {tool_name}", assistant, user_proxy)
return autogen_tool
# Load tools.py
sys.path.insert(0, os.getcwd())
root_directory = os.getcwd()
tools_py_path = os.path.join(root_directory, 'tools.py')
tools_dir_path = Path(root_directory) / 'tools'
tools_module = None
if os.path.isfile(tools_py_path):
print(f"{tools_py_path} exists in the root directory. Loading {tools_py_path} and skipping tools folder.")
tools_module = importlib.import_module("tools")
elif tools_dir_path.is_dir():
print(f"tools folder exists in the root directory. Loading {tool_name} from tools/{tool_name}.py.")
tools_module = importlib.import_module(f"tools.{tool_name}")
# Create autogen_TOOL_NAME_HERE function for each tool
if tools_module is not None:
for name, obj in inspect.getmembers(tools_module):
if inspect.isclass(obj):
globals()[f"autogen_{name}"] = create_autogen_tool_function(name)
def autogen_CodeDocsSearchTool(assistant, user_proxy):
def register_code_docs_search_tool(tool_class, tool_name, tool_description, assistant, user_proxy):
-2
View File
@@ -1,2 +0,0 @@
from .base_tool import BaseTool, Tool, tool
from .autogen_tools import *
-146
View File
@@ -1,146 +0,0 @@
from abc import ABC, abstractmethod
from typing import Any, Callable, Optional, Type
from langchain_core.tools import StructuredTool
from pydantic import BaseModel, ConfigDict, Field, validator
from pydantic.v1 import BaseModel as V1BaseModel
class BaseTool(BaseModel, ABC):
class _ArgsSchemaPlaceholder(V1BaseModel):
pass
model_config = ConfigDict()
name: str
"""The unique name of the tool that clearly communicates its purpose."""
description: str
"""Used to tell the model how/when/why to use the tool."""
args_schema: Type[V1BaseModel] = Field(default_factory=_ArgsSchemaPlaceholder)
"""The schema for the arguments that the tool accepts."""
description_updated: bool = False
"""Flag to check if the description has been updated."""
cache_function: Optional[Callable] = lambda _args, _result: True
"""Function that will be used to determine if the tool should be cached, should return a boolean. If None, the tool will be cached."""
@validator("args_schema", always=True, pre=True)
def _default_args_schema(cls, v: Type[V1BaseModel]) -> Type[V1BaseModel]:
if not isinstance(v, cls._ArgsSchemaPlaceholder):
return v
return type(
f"{cls.__name__}Schema",
(V1BaseModel,),
{
"__annotations__": {
k: v for k, v in cls._run.__annotations__.items() if k != "return"
},
},
)
def model_post_init(self, __context: Any) -> None:
self._generate_description()
super().model_post_init(__context)
def run(
self,
*args: Any,
**kwargs: Any,
) -> Any:
print(f"Using Tool: {self.name}")
return self._run(*args, **kwargs)
@abstractmethod
def _run(
self,
*args: Any,
**kwargs: Any,
) -> Any:
"""Here goes the actual implementation of the tool."""
def to_langchain(self) -> StructuredTool:
self._set_args_schema()
return StructuredTool(
name=self.name,
description=self.description,
args_schema=self.args_schema,
func=self._run,
)
def _set_args_schema(self):
if self.args_schema is None:
class_name = f"{self.__class__.__name__}Schema"
self.args_schema = type(
class_name,
(V1BaseModel,),
{
"__annotations__": {
k: v
for k, v in self._run.__annotations__.items()
if k != "return"
},
},
)
def _generate_description(self):
args = []
for arg, attribute in self.args_schema.schema()["properties"].items():
if "type" in attribute:
args.append(f"{arg}: '{attribute['type']}'")
description = self.description.replace("\n", " ")
self.description = f"{self.name}({', '.join(args)}) - {description}"
class Tool(BaseTool):
func: Callable
"""The function that will be executed when the tool is called."""
def _run(self, *args: Any, **kwargs: Any) -> Any:
return self.func(*args, **kwargs)
def to_langchain(
tools: list[BaseTool | StructuredTool],
) -> list[StructuredTool]:
return [t.to_langchain() if isinstance(t, BaseTool) else t for t in tools]
def tool(*args):
"""
Decorator to create a tool from a function.
"""
def _make_with_name(tool_name: str) -> Callable:
def _make_tool(f: Callable) -> BaseTool:
if f.__doc__ is None:
raise ValueError("Function must have a docstring")
if f.__annotations__ is None:
raise ValueError("Function must have type annotations")
class_name = "".join(tool_name.split()).title()
args_schema = type(
class_name,
(V1BaseModel,),
{
"__annotations__": {
k: v for k, v in f.__annotations__.items() if k != "return"
},
},
)
return Tool(
name=tool_name,
description=f.__doc__,
func=f,
args_schema=args_schema,
)
return _make_tool
if len(args) == 1 and callable(args[0]):
return _make_with_name(args[0].__name__)(args[0])
if len(args) == 1 and isinstance(args[0], str):
return _make_with_name(args[0])
raise ValueError("Invalid arguments")
-116
View File
@@ -1,116 +0,0 @@
from crewai_tools import (
CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, DirectoryReadTool,
FileReadTool, TXTSearchTool, JSONSearchTool, MDXSearchTool, PDFSearchTool, RagTool,
ScrapeElementFromWebsiteTool, ScrapeWebsiteTool, WebsiteSearchTool, XMLSearchTool, YoutubeChannelSearchTool,
YoutubeVideoSearchTool
)
import inspect
# Assuming the tool classes are imported correctly as in the original request
tools_classes = {
'CodeDocsSearchTool': CodeDocsSearchTool,
'CSVSearchTool': CSVSearchTool,
'DirectorySearchTool': DirectorySearchTool,
'DOCXSearchTool': DOCXSearchTool,
'DirectoryReadTool': DirectoryReadTool,
'FileReadTool': FileReadTool,
'TXTSearchTool': TXTSearchTool,
'JSONSearchTool': JSONSearchTool,
'MDXSearchTool': MDXSearchTool,
'PDFSearchTool': PDFSearchTool,
'RagTool': RagTool,
'ScrapeElementFromWebsiteTool': ScrapeElementFromWebsiteTool,
'ScrapeWebsiteTool': ScrapeWebsiteTool,
'WebsiteSearchTool': WebsiteSearchTool,
'XMLSearchTool': XMLSearchTool,
'YoutubeChannelSearchTool': YoutubeChannelSearchTool,
'YoutubeVideoSearchTool': YoutubeVideoSearchTool,
}
for tool_name, tool_class in tools_classes.items():
# Inspect the constructor (__init__) to get its parameters, excluding 'self'
constructor_params = inspect.signature(tool_class.__init__).parameters
param_names = [p for p in constructor_params if p != 'self']
# Attempt to instantiate the tool with dummy or default values for parameters
try:
# Creating a dummy parameters dict with None or empty values based on parameter name
dummy_params = {param: None if param != 'website_url' else 'http://example.com' for param in param_names}
instance = tool_class(**dummy_params)
tool_description = getattr(instance, "description", "No description attribute")
except Exception as e:
tool_description = f"Error instantiating tool for description extraction: {str(e)}"
# Printing tool class name, its constructor parameters, and description
print(f"Tool Class: {tool_name}")
print(f"Constructor Parameters: {', '.join(param_names)}")
print(f"Description: {tool_description}\n")
# Tool Class: CodeDocsSearchTool
# Constructor Parameters: docs_url, kwargs
# Description: Search a Code Docs content(search_query: 'string', docs_url: 'string') - A tool that can be used to semantic search a query from a Code Docs content.
# Tool Class: CSVSearchTool
# Constructor Parameters: csv, kwargs
# Description: Search a CSV's content(search_query: 'string', csv: 'string') - A tool that can be used to semantic search a query from a CSV's content.
# Tool Class: DirectorySearchTool
# Constructor Parameters: directory, kwargs
# Description: Search a directory's content(search_query: 'string', directory: 'string') - A tool that can be used to semantic search a query from a directory's content.
# Tool Class: DOCXSearchTool
# Constructor Parameters: docx, kwargs
# Description: Search a DOCX's content(search_query: 'string', docx: 'string') - A tool that can be used to semantic search a query from a DOCX's content.
# Tool Class: DirectoryReadTool
# Constructor Parameters: directory, kwargs
# Description: List files in directory(directory: 'string') - A tool that can be used to recursively list a directory's content.
# Tool Class: FileReadTool
# Constructor Parameters: file_path, kwargs
# Description: Read a file's content(file_path: 'string') - A tool that can be used to read a file's content.
# Tool Class: TXTSearchTool
# Constructor Parameters: txt, kwargs
# Description: Search a txt's content(search_query: 'string', txt: 'string') - A tool that can be used to semantic search a query from a txt's content.
# Tool Class: JSONSearchTool
# Constructor Parameters: json_path, kwargs
# Description: Search a JSON's content(search_query: 'string', json_path: 'string') - A tool that can be used to semantic search a query from a JSON's content.
# Tool Class: MDXSearchTool
# Constructor Parameters: mdx, kwargs
# Description: Search a MDX's content(search_query: 'string', mdx: 'string') - A tool that can be used to semantic search a query from a MDX's content.
# Tool Class: PDFSearchTool
# Constructor Parameters: pdf, kwargs
# Description: Search a PDF's content(query: 'string', pdf: 'string') - A tool that can be used to semantic search a query from a PDF's content.
# Tool Class: RagTool
# Constructor Parameters: data
# Description: Knowledge base(query: 'string') - A knowledge base that can be used to answer questions.
# Tool Class: ScrapeElementFromWebsiteTool
# Constructor Parameters: website_url, cookies, css_element, kwargs
# Description: Read a website content() - A tool that can be used to read http://example.com's content.
# Tool Class: ScrapeWebsiteTool
# Constructor Parameters: website_url, cookies, kwargs
# Description: Read website content() - A tool that can be used to read http://example.com's content.
# Tool Class: WebsiteSearchTool
# Constructor Parameters: website, kwargs
# Description: Search in a specific website(search_query: 'string', website: 'string') - A tool that can be used to semantic search a query from a specific URL content.
# Tool Class: XMLSearchTool
# Constructor Parameters: xml, kwargs
# Description: Search a XML's content(search_query: 'string', xml: 'string') - A tool that can be used to semantic search a query from a XML's content.
# Tool Class: YoutubeChannelSearchTool
# Constructor Parameters: youtube_channel_handle, kwargs
# Description: Search a Youtube Channels content(search_query: 'string', youtube_channel_handle: 'string') - A tool that can be used to semantic search a query from a Youtube Channels content.
# Tool Class: YoutubeVideoSearchTool
# Constructor Parameters: youtube_video_url, kwargs
# Description: Search a Youtube Video content(search_query: 'string', youtube_video_url: 'string') - A tool that can be used to semantic search a query from a Youtube Video content.
@@ -1,38 +0,0 @@
from typing import Any, Optional
import os
from autogen import ConversableAgent
from scrape_website_tool.scrape_website_tool import ScrapeWebsiteTool
assistant = ConversableAgent(
name="Assistant",
system_message="You are a helpful AI assistant. "
"You can help with website scraping. "
"Return 'TERMINATE' when the task is done.",
llm_config={"config_list": [{"model": "gpt-3.5-turbo", "api_key": os.environ["OPENAI_API_KEY"]}]},
)
user_proxy = ConversableAgent(
name="User",
llm_config=False,
is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"],
human_input_mode="NEVER",
)
from autogen import register_function
from typing import Any
def register_tool(tool_class, tool_name, tool_description):
def tool_func(website_url: str) -> Any:
tool_instance = tool_class(website_url=website_url)
return tool_instance.run()
register_function(
tool_func,
caller=assistant, # The assistant agent can suggest calls to the tool.
executor=user_proxy, # The user proxy agent can execute the tool calls.
name=tool_name, # By default, the function name is used as the tool name.
description=tool_description, # A description of the tool.
)
register_tool(ScrapeWebsiteTool, "scrape_website_tool", "A tool for scraping specific websites")
chat_result = user_proxy.initiate_chat(assistant, message="Scrape the official Nodejs website.")
@@ -1,35 +0,0 @@
from typing import Any, Optional
import os
from autogen import ConversableAgent
from scrape_website_tool.scrape_website_tool import ScrapeWebsiteTool
def scrape_website_tool(website_url: str) -> Any:
scrape_tool = ScrapeWebsiteTool(website_url=website_url)
return scrape_tool.run()
assistant = ConversableAgent(
name="Assistant",
system_message="You are a helpful AI assistant. "
"You can help with website scraping. "
"Return 'TERMINATE' when the task is done.",
llm_config={"config_list": [{"model": "gpt-3.5-turbo", "api_key": os.environ["OPENAI_API_KEY"]}]},
)
user_proxy = ConversableAgent(
name="User",
llm_config=False,
is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"],
human_input_mode="NEVER",
)
from autogen import register_function
# Register the ScrapeWebsiteTool function to the agent and user proxy to add a website scraping tool.
register_function(
scrape_website_tool,
caller=assistant, # The assistant agent can suggest calls to the scrape website tool.
executor=user_proxy, # The user proxy agent can execute the scrape website tool calls.
name="scrape_website_tool", # By default, the function name is used as the tool name.
description="A tool for scraping specific websites", # A description of the tool.
)
chat_result = user_proxy.initiate_chat(assistant, message="Scrape the official Python website.")
-23
View File
@@ -1,23 +0,0 @@
from typing import Any, Optional
import os
from autogen import ConversableAgent
from autogen_tools import autogen_ScrapeWebsiteTool
assistant = ConversableAgent(
name="Assistant",
system_message="You are a helpful AI assistant. "
"You can help with website scraping. "
"Return 'TERMINATE' when the task is done.",
llm_config={"config_list": [{"model": "gpt-3.5-turbo", "api_key": os.environ["OPENAI_API_KEY"]}]},
)
user_proxy = ConversableAgent(
name="User",
llm_config=False,
is_termination_msg=lambda msg: msg.get("content") is not None and "TERMINATE" in msg["content"],
human_input_mode="NEVER",
)
autogen_ScrapeWebsiteTool(assistant, user_proxy)
chat_result = user_proxy.initiate_chat(assistant, message="Scrape the official Nodejs website.")
-134
View File
@@ -1,134 +0,0 @@
import os
from crewai import Agent, Task, Crew
from crewai_tools import (
DirectoryReadTool,
FileReadTool,
SerperDevTool,
WebsiteSearchTool
)
os.environ["SERPER_API_KEY"] = "Your Key"
os.environ["OPENAI_API_KEY"] = "Your Key"
docs_tool = DirectoryReadTool(directory='./blog-posts')
file_tool = FileReadTool()
search_tool = SerperDevTool()
web_rag_tool = WebsiteSearchTool()
researcher = Agent(
role='Market Research Analyst',
goal='Provide up-to-date market analysis of the AI industry',
backstory='An expert analyst with a keen eye for market trends.',
tools=[search_tool, web_rag_tool],
verbose=True
)
writer = Agent(
role='Content Writer',
goal='Craft engaging blog posts about the AI industry',
backstory='A skilled writer with a passion for technology.',
tools=[docs_tool, file_tool],
verbose=True
)
research = Task(
description='Research the latest trends in the AI industry and provide a summary.',
expected_output='A summary of the top 3 trending developments in the AI industry with a unique perspective on their significance.',
agent=researcher
)
write = Task(
description='Write an engaging blog post about the AI industry, based on the research analyst\'s summary. Draw inspiration from the latest blog posts in the directory.',
expected_output='A 4-paragraph blog post formatted in markdown with engaging, informative, and accessible content, avoiding complex jargon.',
agent=writer,
output_file='blog-posts/new_post.md'
)
crew = Crew(
agents=[researcher, writer],
tasks=[research, write],
verbose=2
)
crew.kickoff()
from crewai_tools import DirectoryReadTool
tool = DirectoryReadTool()
toos = DirectoryReadTool(directory='./directory')
from crewai_tools import BaseTool
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, you agent will need this information to use it."
def _run(self, argument: str) -> str:
return "Result from custom tool"
from crewai_tools import tool
@tool("Name of my tool")
def my_tool(question: str) -> str:
return "Result from my tool"
import json
import requests
from crewai import Agent
from crewai.tools import tool
from unstructured.partition.html import partition_html
@tool("Integration with a given API")
def integration_tool(argument: str) -> str:
return "Results from integration tool"
agent = Agent(
role='Research Analyst',
goal='Provide up-to-date market analysis',
backstory='An expert analyst with a keen eye for market trends.',
tools=[integration_tool]
)
from crewai import Agent
from langchain.agents import Tool
from langchain.utilities import GoogleSerperAPIWrapper
os.environ["SERPER_API_KEY"] = "Your Key"
search = GoogleSerperAPIWrapper()
serper_tool = Tool(
name="Intermediate Answer",
func=search.run,
description="Useful for search-based queries",
)
agent = Agent(
role='Research Analyst',
goal='Provide up-to-date market analysis',
backstory='An expert analyst with a keen eye for market trends.',
tools=[serper_tool]
)
# Tool Description
# CodeDocsSearchTool A RAG tool optimized for searching through code documentation and related technical documents.
# CSVSearchTool A RAG tool designed for searching within CSV files, tailored to handle structured data.
# DirectorySearchTool A RAG tool for searching within directories, useful for navigating through file systems.
# DOCXSearchTool A RAG tool aimed at searching within DOCX documents, ideal for processing Word files.
# DirectoryReadTool Facilitates reading and processing of directory structures and their contents.
# FileReadTool Enables reading and extracting data from files, supporting various file formats.
# GithubSearchTool A RAG tool for searching within GitHub repositories, useful for code and documentation search.
# SeperDevTool A specialized tool for development purposes, with specific functionalities under development.
# TXTSearchTool A RAG tool focused on searching within text (.txt) files, suitable for unstructured data.
# JSONSearchTool A RAG tool designed for searching within JSON files, catering to structured data handling.
# MDXSearchTool A RAG tool tailored for searching within Markdown (MDX) files, useful for documentation.
# PDFSearchTool A RAG tool aimed at searching within PDF documents, ideal for processing scanned documents.
# PGSearchTool A RAG tool optimized for searching within PostgreSQL databases, suitable for database queries.
# RagTool A general-purpose RAG tool capable of handling various data sources and types.
# ScrapeElementFromWebsiteTool Enables scraping specific elements from websites, useful for targeted data extraction.
# ScrapeWebsiteTool Facilitates scraping entire websites, ideal for comprehensive data collection.
# WebsiteSearchTool A RAG tool for searching website content, optimized for web data extraction.
# XMLSearchTool A RAG tool designed for searching within XML files, suitable for structured data formats.
# YoutubeChannelSearchTool A RAG tool for searching within YouTube channels, useful for video content analysis.
# YoutubeVideoSearchTool A RAG tool aimed at searching within YouTube videos, ideal for video data extraction.
+2 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "praisonAI"
version = "0.0.18"
version = "0.0.21"
description = "praisonAI application combines AutoGen and CrewAI or similar frameworks into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration."
authors = ["Mervin Praison"]
license = ""
@@ -22,6 +22,7 @@ gradio = ">=4.20.0"
Flask = ">=3.0.0"
markdown = ">=3.5"
crewai-tools = "^0.1.1"
praisonai-tools = ">=0.0.4"
[tool.poetry.dev-dependencies]
pytest = "^8.0.0"
+4 -1
View File
@@ -1,4 +1,7 @@
rich>=13.7
pyautogen>=0.2.19
crewai>=0.22.5
gradio>=4.20.0
gradio>=4.20.0
crewai_tools
duckduckgo_search
praisonai_tools
+10
View File
@@ -17,4 +17,14 @@ elif [ "$1" = "openai" ] || [ -z "$1" ]; then
export OPENAI_API_BASE=https://api.openai.com/v1
export OPENAI_API_KEY=$(echo $OAI_API_KEY)
echo "OpenAI configuration initiated with model $MODEL_NAME."
elif [ "$1" = "ollama" ]; then
# Check for a second argument for the model name, default to a custom model if not provided
MODEL_NAME=${2:-default-ollama-model}
# Set environment variables for Ollama local configuration with dynamic model name
export OPENAI_MODEL_NAME=$MODEL_NAME
export OPENAI_API_BASE=http://127.0.0.1:11434
export OPENAI_API_KEY=$(echo $OLLAMA_API_KEY)
# Set up SSH public key
export SSH_PUBLIC_KEY="ssh-ed25519 AAAA..."
echo "Ollama local model configuration initiated with model $MODEL_NAME.
fi
+3 -2
View File
@@ -5,7 +5,8 @@ def advanced():
agent_file="agents.yaml",
framework="autogen",
)
praison_ai.main()
print(praison_ai)
return praison_ai.main()
if __name__ == "__main__":
advanced()
print(advanced())
+2 -2
View File
@@ -6,7 +6,7 @@ def auto():
framework="autogen"
)
print(praison_ai.framework)
praison_ai.main()
return praison_ai.main()
if __name__ == "__main__":
auto()
print(auto())
+2 -2
View File
@@ -2,7 +2,7 @@ from praisonai import PraisonAI
def main():
praison_ai = PraisonAI(agent_file="agents.yaml")
praison_ai.main()
return praison_ai.main()
if __name__ == "__main__":
main()
print(main())
+42
View File
@@ -0,0 +1,42 @@
framework: crewai
topic: create a movie about cat in mars based on https://blog.celtx.com/how-to-write-a-good-story/
roles:
story_developer:
backstory: Experienced in crafting compelling narratives for a diverse audience.
goal: Develop an engaging storyline for a movie about cats in Mars
role: Story Developer
tasks:
storyline_creation:
description: Create a captivating storyline for a movie about cats in Mars
inspired by the blog post at https://blog.celtx.com/how-to-write-a-good-story/
expected_output: Detailed storyline with key plot points, character motivations,
and setting descriptions.
tools:
- ScrapeWebsiteTool
screenwriter:
backstory: Proficient in translating complex narratives into engaging screenplay
format.
goal: Transform the storyline into a script
role: Screenwriter
tasks:
script_creation:
description: Transform the developed storyline into a script for the movie
about cats in Mars.
expected_output: Complete script with dialogues, scenes, and stage directions
ready for production.
tools:
- ''
director:
backstory: Experienced in visual storytelling and bringing scripts to life on
screen.
goal: Oversee the production of the movie
role: Director
tasks:
movie_production:
description: Take the script and lead the team to produce the movie 'Cats
in Mars' based on the provided content and script.
expected_output: Completed movie ready for distribution with compelling visuals
and engaging storytelling.
tools:
- ''
dependencies: []
+42
View File
@@ -0,0 +1,42 @@
framework: crewai
topic: create a movie about cat in mars
roles:
story_developer:
backstory: Experienced in crafting compelling narratives for a diverse audience.
goal: Develop an engaging storyline for a movie about cats in Mars
role: Story Developer
tasks:
storyline_creation:
description: Create a captivating storyline for a movie about cats in Mars.
Use Internet Search Tool to understand the latest story writing ideas.
expected_output: Detailed storyline with key plot points, character motivations,
and setting descriptions.
tools:
- internet_search_tool
screenwriter:
backstory: Proficient in translating complex narratives into engaging screenplay
format.
goal: Transform the storyline into a script
role: Screenwriter
tasks:
script_creation:
description: Transform the developed storyline into a script for the movie
about cats in Mars.
expected_output: Complete script with dialogues, scenes, and stage directions
ready for production.
tools:
- ''
director:
backstory: Experienced in visual storytelling and bringing scripts to life on
screen.
goal: Oversee the production of the movie
role: Director
tasks:
movie_production:
description: Take the script and lead the team to produce the movie 'Cats
in Mars' based on the provided content and script.
expected_output: Completed movie ready for distribution with compelling visuals
and engaging storytelling.
tools:
- ''
dependencies: []
@@ -41,4 +41,4 @@ register_function(
description="A simple calculator", # A description of the tool.
)
chat_result = user_proxy.initiate_chat(assistant, message="What is (44232 + 13312 / (232 - 32)) * 5?")
chat_result = user_proxy.initiate_chat(assistant, message="What is (44232 + 13312 / (232 - 32)) * 5?")
+99
View File
@@ -0,0 +1,99 @@
import math
import os
from typing import Optional, Type
# Starndard Langchain example
from langchain.agents import create_spark_sql_agent
from langchain.agents.agent_toolkits import SparkSQLToolkit
from langchain.chat_models import ChatOpenAI
# Import things that are needed generically
from langchain.pydantic_v1 import BaseModel, Field
from langchain.tools import BaseTool
from langchain.tools.file_management.read import ReadFileTool
from langchain.utilities.spark_sql import SparkSQL
import autogen
class CircumferenceToolInput(BaseModel):
radius: float = Field()
class CircumferenceTool(BaseTool):
name = "circumference_calculator"
description = "Use this tool when you need to calculate a circumference using the radius of a circle"
args_schema: Type[BaseModel] = CircumferenceToolInput
def _run(self, radius: float):
return float(radius) * 2.0 * math.pi
def get_file_path_of_example():
current_dir = os.path.dirname(__file__)
file_path = os.path.join(current_dir, "radius.txt")
return file_path
# Define a function to generate llm_config from a LangChain tool
def generate_llm_config(tool):
# Define the function schema based on the tool's args_schema
function_schema = {
"name": tool.name.lower().replace(" ", "_"),
"description": tool.description,
"parameters": {
"type": "object",
"properties": {},
"required": [],
},
}
if tool.args is not None:
function_schema["parameters"]["properties"] = tool.args
return function_schema
# Instantiate the ReadFileTool
read_file_tool = ReadFileTool()
custom_tool = CircumferenceTool()
# Construct the llm_config
llm_config = {
# Generate functions config for the Tool
"functions": [
generate_llm_config(custom_tool),
generate_llm_config(read_file_tool),
],
"config_list": [{"model": "gpt-3.5-turbo", "api_key": os.environ["OPENAI_API_KEY"]}],
"timeout": 120,
}
user_proxy = autogen.UserProxyAgent(
name="user_proxy",
is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE"),
human_input_mode="NEVER",
max_consecutive_auto_reply=10,
code_execution_config={
"work_dir": "coding",
"use_docker": False,
}, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.
)
# Register the tool and start the conversation
user_proxy.register_function(
function_map={
custom_tool.name: custom_tool._run,
read_file_tool.name: read_file_tool._run,
}
)
chatbot = autogen.AssistantAgent(
name="chatbot",
system_message="For coding tasks, only use the functions you have been provided with. Reply TERMINATE when the task is done.",
llm_config=llm_config,
)
user_proxy.initiate_chat(
chatbot,
message=f"Read the file with the path {get_file_path_of_example()}, then calculate the circumference of a circle that has a radius of that files contents.", # 7.81mm in the file
llm_config=llm_config,
)
+71
View File
@@ -0,0 +1,71 @@
import os
from crewai import Agent, Task, Crew
from duckduckgo_search import DDGS
from langchain.tools import tool
@tool("Internet Search Tool")
def internet_search_tool(query: str) -> list:
"""Search Internet for relevant information based on a query."""
ddgs = DDGS()
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
return results
# Define agents
researcher = Agent(
role='Researcher',
goal='Gather and analyze information on specific topics',
verbose=True,
backstory=(
"As a seasoned researcher, you have a keen eye for detail and a "
"deep understanding of your field. You're adept at sifting through "
"information to find the most relevant and accurate data."
),
tools=[internet_search_tool],
allow_delegation=True
)
writer = Agent(
role='Writer',
goal='Compose informative and engaging articles based on research findings',
verbose=True,
backstory=(
"With a talent for storytelling, you translate complex ideas into "
"clear, compelling narratives. Your articles are well-researched, "
"thought-provoking, and accessible to a broad audience."
),
tools=[internet_search_tool],
allow_delegation=False
)
# Define tasks
research_task = Task(
description=(
"Investigate the latest trends in renewable energy technologies. "
"Identify key advancements, challenges, and potential impacts on "
"global energy policies."
),
expected_output='A detailed report summarizing the findings.',
tools=[internet_search_tool],
agent=researcher,
)
writing_task = Task(
description=(
"Based on the research findings, write an article that highlights "
"the importance of renewable energy innovations. The article should "
"educate the public on how these technologies can contribute to "
"sustainable development."
),
expected_output='An engaging and informative article suitable for publication.',
tools=[internet_search_tool],
agent=writer,
)
# Create and kick off the crew
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task]
)
result = crew.kickoff(inputs={'topic': 'renewable energy'})
print(result)
+1
View File
@@ -0,0 +1 @@
7.81mm
+38 -22
View File
@@ -1,47 +1,63 @@
# tests/test.py
# from .debug import * # Uncomment this line to import the debug.py file for debugging
import unittest
import os
import subprocess
from praisonai.cli import PraisonAI
from .advanced_example import advanced
from .basic_example import main
from .auto_example import auto
class TestGenerateCrewAndKickoff(unittest.TestCase):
def test_generate_crew_and_kickoff_with_autogen_framework(self):
class TestPraisonAIFramework(unittest.TestCase):
def test_main_with_autogen_framework(self):
praison_ai = PraisonAI(agent_file='tests/autogen-agents.yaml')
result = praison_ai.generate_crew_and_kickoff()
# Assert the result
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
def test_generate_crew_and_kickoff_with_custom_framework(self):
def test_main_with_custom_framework(self):
praison_ai = PraisonAI(agent_file='tests/crewai-agents.yaml')
result = praison_ai.generate_crew_and_kickoff()
# Assert the result
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
class TestPraisonAICommand(unittest.TestCase):
def test_main_with_internet_search_tool(self):
praison_ai = PraisonAI(agent_file='tests/search-tool-agents.yaml')
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
def test_main_with_built_in_tool(self):
praison_ai = PraisonAI(agent_file='tests/inbuilt-tool-agents.yaml')
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
class TestPraisonAICommandLine(unittest.TestCase):
def run_command(self, command):
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, text=True)
return result.stdout
def test_praisonai_command(self):
command = "praisonai --framework autogen --auto create movie script about cat in mars"
result = os.popen(command).read()
self.assertIn('### Task Output ###', result)
class TestPraisonAIInitCommand(unittest.TestCase):
result = self.run_command(command)
self.assertIn('TERMINATE', result)
def test_praisonai_init_command(self):
command = "praisonai --framework autogen --init create movie script about cat in mars"
result = os.popen(command).read()
self.assertIn('### Task Output ###', result)
result = self.run_command(command)
self.assertIn('created successfully', result)
class TestBasicExample(unittest.TestCase):
class TestExamples(unittest.TestCase):
def test_basic_example(self):
main()
# Assuming main() has been adjusted to return a value for assertion
result = main()
self.assertIsNotNone(result) # Adjust this assertion based on the expected outcome of main()
class TestAdvancedExample(unittest.TestCase):
def test_advanced_example(self):
advanced()
class TestAutoExample(unittest.TestCase):
# Assuming advanced() returns a value suitable for assertion
result = advanced()
self.assertIsNotNone(result) # Adjust this assertion as needed
def test_auto_example(self):
auto()
# Assuming auto() returns a value that can be asserted
result = auto()
self.assertIsNotNone(result) # Adjust this assertion according to what auto() is expected to do
if __name__ == '__main__':
unittest.main()
+25
View File
@@ -0,0 +1,25 @@
# tests/test_agents_playbook.py
import unittest
import subprocess
from praisonai import PraisonAI
class TestPraisonAIFramework(unittest.TestCase):
def test_main_with_autogen_framework(self):
praison_ai = PraisonAI(agent_file='tests/autogen-agents.yaml')
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
def test_main_with_custom_framework(self):
praison_ai = PraisonAI(agent_file='tests/crewai-agents.yaml')
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
def test_main_with_internet_search_tool(self):
praison_ai = PraisonAI(agent_file='tests/search-tool-agents.yaml')
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
def test_main_with_built_in_tool(self):
praison_ai = PraisonAI(agent_file='tests/inbuilt-tool-agents.yaml')
result = praison_ai.main()
self.assertIn('### Task Output ###', result)
View File
Whitespace-only changes.
+9
View File
@@ -0,0 +1,9 @@
from duckduckgo_search import DDGS
from langchain.tools import tool
@tool("Internet Search Tool")
def internet_search_tool(query: str) -> list:
"""Search Internet for relevant information based on a query."""
ddgs = DDGS()
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
return results
+10 -6
View File
@@ -1,8 +1,12 @@
# tools.py
from duckduckgo_search import DDGS
from praisonai_tools import BaseTool
@tool("Internet Search Tool")
def internet_search_tool(query: str) -> list:
"""Search Internet for relevant information based on a query."""
ddgs = DDGS()
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
return results
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
View File
Whitespace-only changes.
+11
View File
@@ -0,0 +1,11 @@
from duckduckgo_search import DDGS
from praisonai_tools import BaseTool
class InternetSearchTool(BaseTool):
name: str = "Internet Search Tool"
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