├── .DS_Store ├── .devcontainer └── devcontainer.json ├── .gitattributes ├── .github └── workflows │ ├── lint_commit.yml │ └── run_ruffus_tests.yml ├── .pre-commit-config.yaml ├── .vscode └── settings.json ├── Dockerfile.dev ├── README.MD ├── assets └── logo.png └── taskforce ├── .env.example ├── .gitignore ├── Makefile ├── crews ├── __init__.py ├── instagram_post │ ├── __init__.py │ ├── agents.py │ ├── crew.py │ ├── tasks.py │ └── test_crew.py ├── meeting_prep │ ├── __init__.py │ ├── agents.py │ ├── crew.py │ ├── tasks.py │ └── test_crew.py ├── product_photographer │ ├── __init__.py │ ├── agents.py │ ├── crew.py │ ├── tasks.py │ └── test_crew.py ├── stock_analysis │ ├── __init__.py │ ├── agents.py │ ├── crew.py │ ├── tasks.py │ └── test_crew.py ├── template_crew │ ├── __init__.py │ ├── agents.py │ ├── crew.py │ ├── tasks.py │ └── test_crew.py └── trip_planner │ ├── __init__.py │ ├── agents.py │ ├── crew.py │ ├── tasks.py │ └── test_crew.py ├── lib ├── __init__.py ├── interfaces │ ├── CrewManager.py │ ├── TestInterface.py │ └── __init__.py ├── models.py ├── tasks_utils.py └── tools │ ├── __init__.py │ ├── browser_tools.py │ ├── calculator_tools.py │ ├── exa_search_tools.py │ ├── search_tools.py │ ├── sec_tools.py │ └── utils.py ├── main.py ├── poetry.lock └── pyproject.toml /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/.DS_Store -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TaskForce", 3 | "build": { 4 | // Sets the run context to one level up instead of the .devcontainer folder. 5 | "context": "..", 6 | // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. 7 | "dockerfile": "../Dockerfile.dev" 8 | }, 9 | "features": { 10 | "ghcr.io/devcontainers/features/git:1": {}, 11 | "ghcr.io/devcontainers-contrib/features/black:2": {}, 12 | "ghcr.io/devcontainers-contrib/features/mypy:2": {}, 13 | "ghcr.io/devcontainers-contrib/features/poetry:2": {}, 14 | "ghcr.io/devcontainers-contrib/features/pylint:2": {} 15 | }, 16 | 17 | "forwardPorts": [8000, 8000], 18 | 19 | "customizations": { 20 | // Configure properties specific to VS Code. 21 | "vscode": { 22 | // Set *default* container specific settings.json values on container create. 23 | "settings": { 24 | "git.openRepositoryInParentFolders": "always", 25 | "github.copilot.enable": { 26 | "*": true, 27 | "yaml": true, 28 | "plaintext": true, 29 | "markdown": true, 30 | "scminput": false 31 | }, 32 | "editor.rulers": [79], 33 | "[python]": { 34 | "analysis.typeCheckingMode": "basic", 35 | "analysis.autoImportCompletions": true, 36 | "editor.tabSize": 4, 37 | "editor.insertSpaces": true, 38 | "editor.formatOnSave": true, 39 | "editor.defaultFormatter": "charliermarsh.ruff" 40 | } 41 | }, 42 | // Add the IDs of extensions you want installed when the container is created. 43 | "extensions": [ 44 | "ms-python.python", 45 | "charliermarsh.ruff", 46 | "esbenp.prettier-vscode", 47 | "GitHub.copilot", 48 | "usernamehw.errorlens", 49 | "tamasfe.even-better-toml" 50 | ] 51 | } 52 | }, 53 | 54 | "workspaceMount": "source=${localWorkspaceFolder},target=/src,type=bind", 55 | "workspaceFolder": "/src/taskforce/", 56 | 57 | "postAttachCommand": "pre-commit install --overwrite" 58 | 59 | // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root. 60 | // "remoteUser": "devcontainer" 61 | } 62 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/lint_commit.yml: -------------------------------------------------------------------------------- 1 | name: Lint and Commit 2 | on: 3 | pull_request: 4 | types: [opened, synchronize] 5 | 6 | jobs: 7 | lint: 8 | name: Lint and Commit 9 | defaults: 10 | run: 11 | working-directory: taskforce 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: chartboost/ruff-action@v1 16 | with: 17 | args: format 18 | - uses: stefanzweifel/git-auto-commit-action@v4 19 | with: 20 | commit_message: 'style fixes by ruff' 21 | -------------------------------------------------------------------------------- /.github/workflows/run_ruffus_tests.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | types: [opened, synchronize] 4 | workflow_dispatch: 5 | 6 | name: Run Tests 7 | 8 | jobs: 9 | deploy: 10 | name: Tests 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | working-directory: taskforce 15 | steps: 16 | #---------------------------------------------- 17 | # check-out repo and set-up python 18 | #---------------------------------------------- 19 | - name: Check out repository 20 | uses: actions/checkout@v4 21 | - name: Install poetry 22 | run: pipx install poetry 23 | - uses: actions/setup-python@v5 24 | with: 25 | python-version: '3.11' 26 | cache: 'poetry' 27 | #---------------------------------------------- 28 | # install dependencies if cache does not exist 29 | #---------------------------------------------- 30 | - name: Install dependencies 31 | run: poetry install --no-interaction --no-root 32 | #---------------------------------------------- 33 | # Run tests and publish results 34 | #---------------------------------------------- 35 | - uses: pavelzw/pytest-action@v2 36 | with: 37 | emoji: true 38 | verbose: true 39 | job-summary: true 40 | custom-pytest: 'cd taskforce && poetry run pytest ' 41 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.4.0 6 | hooks: 7 | - id: check-added-large-files 8 | - id: check-toml 9 | - id: check-yaml 10 | args: 11 | - --unsafe 12 | - id: end-of-file-fixer 13 | - id: trailing-whitespace 14 | - repo: https://github.com/charliermarsh/ruff-pre-commit 15 | rev: v0.1.2 16 | hooks: 17 | - id: ruff 18 | args: 19 | - --fix 20 | - id: ruff-format 21 | ci: 22 | autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks 23 | autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate 24 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.analysis.typeCheckingMode": "basic", 3 | "python.analysis.autoFormatStrings": true, 4 | "editor.defaultFormatter": "charliermarsh.ruff", 5 | "[python]": { 6 | "editor.defaultFormatter": "charliermarsh.ruff" 7 | }, 8 | "python.analysis.autoImportCompletions": true 9 | } 10 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM python:3.11-slim as dev_base 2 | 3 | # Set environment variables to: 4 | # - Prevent Python from writing pyc files to disc (useful in production) 5 | # - Make Python output unbuffered, which is useful in Docker containers 6 | # - Define an environment variable for versioning that can be used in your application 7 | ENV PYTHONDONTWRITEBYTECODE=1 \ 8 | PYTHONUNBUFFERED=1 \ 9 | PYCURL_SSL_LIBRARY=openssl \ 10 | VERSION=1.0.0 11 | 12 | WORKDIR /src/taskforce 13 | 14 | # Use `apt-get install -y --no-install-recommends` to only install essential packages and avoid extra packages 15 | # Cleanup cache and temporary files in the same layer to keep the image size small 16 | RUN apt-get update && \ 17 | apt-get install -y --no-install-recommends gcc libffi-dev openssl libcurl4-openssl-dev libssl-dev git libc-dev make && \ 18 | apt-get clean && \ 19 | rm -rf /var/lib/apt/lists/* /root/.cache 20 | 21 | # Install poetry in the base image to avoid reinstalling it every time a dependency changes 22 | # This is efficient if you're using a multi-stage build and your dependencies don't change as often as your code 23 | RUN pip install --no-cache-dir poetry 24 | 25 | # Copy the pyproject.toml and poetry.lock files first to cache the dependencies installation 26 | # This is beneficial if your project's source code changes more frequently than your dependencies 27 | COPY ./taskforce/pyproject.toml ./taskforce/poetry.lock* /src/taskforce/ 28 | 29 | # Project dependencies: 30 | # Disable virtualenv creation by poetry to install dependencies globally in the image 31 | # Install runtime dependencies only, without dev-dependencies 32 | RUN poetry config virtualenvs.create false && \ 33 | poetry install --no-interaction --no-ansi --no-root 34 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 |
2 | 3 | Logo of TaskForce 4 | 5 | # **TaskForce** 6 | 7 | 🤖 **TaskForce**: A community based framework around [CrewAi](https://crewai.com/) for collaborating AI agents. 8 | 9 | [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) 10 | 11 |
12 | 13 | # Getting Started 14 | 15 | ## Options 16 | 17 | - [Run inside the dev container](#dev-container) 18 | - [Install the dependencies locally](#local-installation) 19 | 20 | ## Project structure 21 | 22 | ```bash 23 | . 24 | ├── .github 25 | │ ├── workflows 26 | ├── .devcontainer 27 | │ ├── devcontainer.json # Dev container configuration 28 | ├── assets 29 | │ ├──... # Images and other assets 30 | ├── taskforce 31 | │ ├── lib 32 | │ │ ├── interfaces 33 | │ │ ├── ... # Interfaces for the framework 34 | │ │ ├── tools 35 | │ │ ├── ... # Tools folders 36 | │ │ ├── models.py # General models for the framework 37 | │ │ ├── task_utils.py 38 | │ ├── crews 39 | │ │ ├── ... # Crews folders 40 | ├── .env.example # Example of the .env file, not all the variables are required 41 | ├── Dockerfile.dev 42 | ├── README.md 43 | 44 | ``` 45 | 46 | # Development 47 | 48 | ## Dev Container 49 | 50 | ### Prerequisites 51 | 52 | - [Docker](https://www.docker.com/products/docker-desktop) 53 | - [VSCode](https://code.visualstudio.com/) 54 | - [Dev Container Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) 55 | 56 | ### Running the Dev Container 57 | 58 | - Open the project in VSCode 59 | - Open the `Command Palette` (Cmd+Shift+P) 60 | - Select "Reopen in Container" 61 | - Wait for the container to build 62 | - Run `make run-tests` to run the tests 63 | - Done! 64 | 65 | ## Local Installation 66 | 67 | ### Installing Dependencies 68 | 69 | ```bash 70 | poetry lock 71 | poetry install 72 | ``` 73 | 74 | ### Virtual Env 75 | 76 | ```bash 77 | poetry shell 78 | ``` 79 | 80 | ### Pre-commit hooks 81 | 82 | ```bash 83 | pre-commit install 84 | ``` 85 | 86 | ### Running Tests 87 | 88 | ```bash 89 | poetry run pytest 90 | ``` 91 | 92 | ### Contribution 93 | 94 | TaskForce is open-source and we welcome contributions. If you're looking to contribute, please: 95 | 96 | - Fork the repository. 97 | - Create a new branch for your updates. 98 | - Add your agent, tool or any other improvement. 99 | - Send a pull request. 100 | 101 | ## License 102 | 103 | TaskForce is released under the MIT License. 104 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/assets/logo.png -------------------------------------------------------------------------------- /taskforce/.env.example: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY= 2 | 3 | SERPER_API_KEY= 4 | 5 | SEC_API_API_KEY= 6 | 7 | EXA_API_KEY= 8 | 9 | BROWSERLESS_API_KEY= 10 | -------------------------------------------------------------------------------- /taskforce/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.env.local 3 | *.env.development.local 4 | *.env.test.local 5 | *.env.production.local 6 | .ruff_cache 7 | .venv 8 | .mp3 9 | 10 | # IDE 11 | .idea 12 | .vscode 13 | 14 | # Logs 15 | *.log 16 | 17 | # Build 18 | build 19 | dist 20 | node_modules 21 | npm-debug.log* 22 | yarn-debug.log* 23 | 24 | # Python 25 | *.pyc 26 | 27 | # Extra 28 | *.DS_Store 29 | *.mp3 30 | *.wav 31 | -------------------------------------------------------------------------------- /taskforce/Makefile: -------------------------------------------------------------------------------- 1 | install-poetry: 2 | pip install poetry 3 | 4 | install-deps: 5 | poetry install --no-root 6 | 7 | install: 8 | poetry install --no-root 9 | 10 | install-deps-prod: 11 | poetry install --no-dev --no-root 12 | 13 | run-app: 14 | poetry run python main.py 15 | 16 | run: 17 | poetry run python main.py 18 | 19 | lint: 20 | ruff format 21 | ruff --fix 22 | 23 | run-tests: 24 | poetry run pytest run_tests.py --emoji 25 | -------------------------------------------------------------------------------- /taskforce/crews/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/instagram_post/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/instagram_post/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/instagram_post/agents.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent 5 | 6 | from lib.tools.browser_tools import BrowserTools 7 | from lib.tools.search_tools import SearchTools 8 | 9 | verbose = bool(os.environ.get("VERBOSE", False)) 10 | 11 | 12 | class InstagramPostAgents: 13 | def product_competitor_agent(self): 14 | return Agent( 15 | role="Lead Market Analyst", 16 | goal=dedent( 17 | """\ 18 | Conduct amazing analysis of the products and 19 | competitors, providing in-depth insights to guide 20 | marketing strategies.""" 21 | ), 22 | backstory=dedent( 23 | """\ 24 | As the Lead Market Analyst at a premier 25 | digital marketing firm, you specialize in dissecting 26 | online business landscapes.""" 27 | ), 28 | tools=[BrowserTools.scrape_and_summarize_website, SearchTools.search_internet], 29 | verbose=verbose, 30 | ) 31 | 32 | def strategy_planner_agent(self): 33 | return Agent( 34 | role="Chief Marketing Strategist", 35 | goal=dedent( 36 | """\ 37 | Synthesize amazing insights from product analysis 38 | to formulate incredible marketing strategies.""" 39 | ), 40 | backstory=dedent( 41 | """\ 42 | You are the Chief Marketing Strategist at 43 | a leading digital marketing agency, known for crafting 44 | bespoke strategies that drive success.""" 45 | ), 46 | tools=[ 47 | BrowserTools.scrape_and_summarize_website, 48 | SearchTools.search_internet, 49 | SearchTools.search_instagram, 50 | ], 51 | verbose=verbose, 52 | ) 53 | 54 | def creative_content_creator_agent(self): 55 | return Agent( 56 | role="Creative Content Creator", 57 | goal=dedent( 58 | """\ 59 | Develop compelling and innovative content 60 | for social media campaigns, with a focus on creating 61 | high-impact Instagram ad copies.""" 62 | ), 63 | backstory=dedent( 64 | """\ 65 | As a Creative Content Creator at a top-tier 66 | digital marketing agency, you excel in crafting narratives 67 | that resonate with audiences on social media. 68 | Your expertise lies in turning marketing strategies 69 | into engaging stories and visual content that capture 70 | attention and inspire action.""" 71 | ), 72 | tools=[ 73 | BrowserTools.scrape_and_summarize_website, 74 | SearchTools.search_internet, 75 | SearchTools.search_instagram, 76 | ], 77 | verbose=verbose, 78 | ) 79 | 80 | def senior_photographer_agent(self): 81 | return Agent( 82 | role="Senior Photographer", 83 | goal=dedent( 84 | """\ 85 | Take the most amazing photographs for instagram ads that 86 | capture emotions and convey a compelling message.""" 87 | ), 88 | backstory=dedent( 89 | """\ 90 | As a Senior Photographer at a leading digital marketing 91 | agency, you are an expert at taking amazing photographs that 92 | inspire and engage, you're now working on a new campaign for a super 93 | important customer and you need to take the most amazing photograph.""" 94 | ), 95 | tools=[ 96 | BrowserTools.scrape_and_summarize_website, 97 | SearchTools.search_internet, 98 | SearchTools.search_instagram, 99 | ], 100 | verbose=verbose, 101 | ) 102 | 103 | def chief_creative_director_agent(self): 104 | return Agent( 105 | role="Chief Creative Director", 106 | goal=dedent( 107 | """\ 108 | Oversee the work done by your team to make sure it's the best 109 | possible and aligned with the product's goals, review, approve, 110 | ask clarifying question or delegate follow up work if necessary to make 111 | decisions""" 112 | ), 113 | backstory=dedent( 114 | """\ 115 | You're the Chief Content Officer of leading digital 116 | marketing specialized in product branding. You're working on a new 117 | customer, trying to make sure your team is crafting the best possible 118 | content for the customer.""" 119 | ), 120 | tools=[ 121 | BrowserTools.scrape_and_summarize_website, 122 | SearchTools.search_internet, 123 | SearchTools.search_instagram, 124 | ], 125 | verbose=verbose, 126 | ) 127 | -------------------------------------------------------------------------------- /taskforce/crews/instagram_post/crew.py: -------------------------------------------------------------------------------- 1 | from crews.instagram_post.agents import InstagramPostAgents 2 | from crews.instagram_post.tasks import InstagramPostTasks 3 | from crews.product_photographer.crew import ProductPhotographerCrew 4 | from lib.interfaces.CrewManager import CrewManager 5 | 6 | 7 | class InstagramPostCrew(CrewManager): 8 | """ 9 | Crew for Instagram post, 10 | Given a product website, product details and objective, 11 | the crew will generate a post copy and image description. 12 | """ 13 | 14 | def __init__(self, product_website, product_details, objective): 15 | self.product_website = product_website 16 | self.product_details = product_details 17 | self.objective = objective 18 | 19 | super().__init__() 20 | 21 | def _set_agents(self): 22 | agents = InstagramPostAgents() 23 | self.agents = { 24 | "product_competitor_agent": agents.product_competitor_agent(), 25 | "strategy_planner_agent": agents.strategy_planner_agent(), 26 | "creative_agent": agents.creative_content_creator_agent(), 27 | } 28 | 29 | def _set_tasks(self): 30 | tasks = InstagramPostTasks() 31 | website_analysis = tasks.product_analysis( 32 | self.agents["product_competitor_agent"], self.product_website, self.product_details 33 | ) 34 | market_analysis = tasks.competitor_analysis( 35 | self.agents["product_competitor_agent"], self.product_website, self.product_details 36 | ) 37 | campaign_development = tasks.campaign_development( 38 | self.agents["strategy_planner_agent"], self.product_website, self.product_details 39 | ) 40 | write_copy = tasks.instagram_ad_copy(self.agents["creative_agent"]) 41 | 42 | self.tasks = [ 43 | website_analysis, 44 | market_analysis, 45 | campaign_development, 46 | write_copy, 47 | ] 48 | 49 | def run(self): 50 | post_text = self.crew.kickoff() 51 | 52 | post_image_description = ProductPhotographerCrew( 53 | copy=post_text, 54 | product_website=self.product_website, 55 | product_details=self.product_details, 56 | ).run() 57 | 58 | return {"post_copy": post_text, "post_image_description": post_image_description} 59 | -------------------------------------------------------------------------------- /taskforce/crews/instagram_post/tasks.py: -------------------------------------------------------------------------------- 1 | from textwrap import dedent 2 | 3 | from crewai import Task 4 | 5 | 6 | class InstagramPostTasks: 7 | def product_analysis(self, agent, product_website, product_details): 8 | return Task( 9 | description=dedent( 10 | f"""\ 11 | Analyze the given product website: {product_website}. 12 | Extra details provided by the customer: {product_details}. 13 | 14 | Focus on identifying unique features, benefits, 15 | and the overall narrative presented. 16 | 17 | Your final report should clearly articulate the 18 | product's key selling points, its market appeal, 19 | and suggestions for enhancement or positioning. 20 | Emphasize the aspects that make the product stand out. 21 | 22 | Keep in mind, attention to detail is crucial for 23 | a comprehensive analysis. It's currenlty 2024. 24 | """ 25 | ), 26 | agent=agent, 27 | ) 28 | 29 | def competitor_analysis(self, agent, product_website, product_details): 30 | return Task( 31 | description=dedent( 32 | f"""\ 33 | Explore competitor of: {product_website}. 34 | Extra details provided by the customer: {product_details}. 35 | 36 | Identify the top 3 competitors and analyze their 37 | strategies, market positioning, and customer perception. 38 | 39 | Your final report MUST include BOTH all context about {product_website} 40 | and a detailed comparison to whatever competitor they have competitors. 41 | """ 42 | ), 43 | agent=agent, 44 | ) 45 | 46 | def campaign_development(self, agent, product_website, product_details): 47 | return Task( 48 | description=dedent( 49 | f"""\ 50 | You're creating a targeted marketing campaign for: {product_website}. 51 | Extra details provided by the customer: {product_details}. 52 | 53 | To start this campaign we will need a strategy and creative content ideas. 54 | It should be meticulously designed to captivate and engage 55 | the product's target audience. 56 | 57 | Based on your ideas your co-workers will create the content for the campaign. 58 | 59 | Your final answer MUST be ideas that will resonate with the audience and 60 | also include ALL context you have about the product and the customer. 61 | """ 62 | ), 63 | agent=agent, 64 | ) 65 | 66 | def instagram_ad_copy(self, agent): 67 | return Task( 68 | description=dedent( 69 | """\ 70 | Craft an engaging Instagram post copy. 71 | The copy should be punchy, captivating, concise, 72 | and aligned with the product marketing strategy. 73 | 74 | Focus on creating a message that resonates with 75 | the target audience and highlights the product's 76 | unique selling points. 77 | 78 | Your ad copy must be attention-grabbing and should 79 | encourage viewers to take action, whether it's 80 | visiting the website, making a purchase, or learning 81 | more about the product. 82 | 83 | Your final answer MUST be 3 options for an ad copy for instagram that 84 | not only informs but also excites and persuades the audience. 85 | """ 86 | ), 87 | agent=agent, 88 | ) 89 | 90 | def take_photograph_task(self, agent, copy, product_website, product_details): 91 | return Task( 92 | description=dedent( 93 | f"""\ 94 | You are working on a new campaign for a super important customer, 95 | and you MUST take the most amazing photo ever for an instagram post 96 | regarding the product, you have the following copy: 97 | {copy} 98 | 99 | This is the product you are working with: {product_website}. 100 | Extra details provided by the customer: {product_details}. 101 | 102 | Imagine what the photo you wanna take describe it in a paragraph. 103 | Here are some examples for you follow: 104 | - high tech airplane in a beautiful blue sky in a beautiful sunset super crispy beautiful 4k, professional wide shot 105 | - the last supper, with Jesus and his disciples, breaking bread, close shot, soft lighting, 4k, crisp 106 | - an bearded old man in the snows, using very warm clothing, with mountains full of snow behind him, soft lighting, 4k, crisp, close up to the camera 107 | 108 | Think creatively and focus on how the image can capture the audience's 109 | attention. Don't show the actual product on the photo. 110 | 111 | Your final answer must be 3 options of photographs, each with 1 paragraph 112 | describing the photograph exactly like the examples provided above. 113 | """ # noqa: E501 114 | ), 115 | agent=agent, 116 | ) 117 | 118 | def review_photo(self, agent, product_website, product_details): 119 | return Task( 120 | description=dedent( 121 | f"""\ 122 | Review the photos you got from the senior photographer. 123 | Make sure it's the best possible and aligned with the product's goals, 124 | review, approve, ask clarifying question or delegate follow up work if 125 | necessary to make decisions. When delegating work send the full draft 126 | as part of the information. 127 | 128 | This is the product you are working with: {product_website}. 129 | Extra details provided by the customer: {product_details}. 130 | 131 | Here are some examples on how the final photographs should look like: 132 | - high tech airplane in a beautiful blue sky in a beautiful sunset super crispy beautiful 4k, professional wide shot 133 | - the last supper, with Jesus and his disciples, breaking bread, close shot, soft lighting, 4k, crisp 134 | - an bearded old man in the snows, using very warm clothing, with mountains full of snow behind him, soft lighting, 4k, crisp, close up to the camera 135 | 136 | Your final answer must be 3 reviewed options of photographs, 137 | each with 1 paragraph description following the examples provided above. 138 | """ # noqa: E501 139 | ), 140 | agent=agent, 141 | ) 142 | -------------------------------------------------------------------------------- /taskforce/crews/instagram_post/test_crew.py: -------------------------------------------------------------------------------- 1 | from crews.instagram_post.crew import InstagramPostCrew 2 | from lib.interfaces.TestInterface import TestCrewInterface 3 | 4 | 5 | class InstagramPostTest(TestCrewInterface): 6 | objective = "To promote a product" 7 | product_details = "This is a product description" 8 | product_website = "www.productwebsite.com" 9 | 10 | def init_class(self): 11 | crew = InstagramPostCrew( 12 | objective=self.objective, 13 | product_details=self.product_details, 14 | product_website=self.product_website, 15 | ) 16 | return crew 17 | 18 | def test_crew_company(self): 19 | crew = self.init_class() 20 | assert crew.objective == self.objective 21 | assert crew.product_details == self.product_details 22 | assert crew.product_website == self.product_website 23 | 24 | def test_crew_agents(self): 25 | crew = self.init_class() 26 | assert len(crew.agents) > 0 27 | 28 | def test_crew_tasks(self): 29 | crew = self.init_class() 30 | assert len(crew.tasks) > 0 31 | -------------------------------------------------------------------------------- /taskforce/crews/meeting_prep/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/meeting_prep/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/meeting_prep/agents.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent 5 | 6 | from lib.tools.exa_search_tools import ExaSearchTool 7 | 8 | verbose = bool(os.environ.get("VERBOSE", False)) 9 | 10 | 11 | class MeetingPreparationAgents: 12 | def research_agent(self): 13 | return Agent( 14 | role="Research Specialist", 15 | goal="Conduct thorough research on people and companies involved in the meeting", 16 | tools=ExaSearchTool.tools(), 17 | backstory=dedent( 18 | """\ 19 | As a Research Specialist, your mission is to uncover detailed information 20 | about the individuals and entities participating in the meeting. Your insights 21 | will lay the groundwork for strategic meeting preparation.""" 22 | ), 23 | verbose=verbose, 24 | ) 25 | 26 | def industry_analysis_agent(self): 27 | return Agent( 28 | role="Industry Analyst", 29 | goal="Analyze the current industry trends, challenges, and opportunities", 30 | tools=ExaSearchTool.tools(), 31 | backstory=dedent( 32 | """\ 33 | As an Industry Analyst, your analysis will identify key trends, 34 | challenges facing the industry, and potential opportunities that 35 | could be leveraged during the meeting for strategic advantage.""" 36 | ), 37 | verbose=verbose, 38 | ) 39 | 40 | def meeting_strategy_agent(self): 41 | return Agent( 42 | role="Meeting Strategy Advisor", 43 | goal="Develop talking points, questions, and strategic angles for the meeting", 44 | tools=ExaSearchTool.tools(), 45 | backstory=dedent( 46 | """\ 47 | As a Strategy Advisor, your expertise will guide the development of 48 | talking points, insightful questions, and strategic angles 49 | to ensure the meeting's objectives are achieved.""" 50 | ), 51 | verbose=verbose, 52 | ) 53 | 54 | def summary_and_briefing_agent(self): 55 | return Agent( 56 | role="Briefing Coordinator", 57 | goal="Compile all gathered information into a concise, informative briefing document", 58 | tools=ExaSearchTool.tools(), 59 | backstory=dedent( 60 | """As the Briefing Coordinator, your role is to consolidate the research, 61 | analysis, and strategic insights.""" 62 | ), 63 | verbose=verbose, 64 | ) 65 | -------------------------------------------------------------------------------- /taskforce/crews/meeting_prep/crew.py: -------------------------------------------------------------------------------- 1 | from crews.meeting_prep.agents import MeetingPreparationAgents 2 | from crews.meeting_prep.tasks import MeetingPreparationTasks 3 | from lib.interfaces.CrewManager import CrewManager 4 | 5 | 6 | class MeetingPrepCrew(CrewManager): 7 | """ 8 | Crew for meeting preparation, 9 | Given a list of participants, context, and objective, 10 | the crew will help you prepare for the meeting by researching, analyzing and strategizing. 11 | """ 12 | 13 | def __init__(self, participants: str, context: str, objective: str): 14 | self.participants = participants 15 | self.context = context 16 | self.objective = objective 17 | 18 | super().__init__() 19 | 20 | def _set_agents(self): 21 | agents = MeetingPreparationAgents() 22 | self.agents = { 23 | "researcher_agent": agents.research_agent(), 24 | "industry_analyst_agent": agents.industry_analysis_agent(), 25 | "meeting_strategy_agent": agents.meeting_strategy_agent(), 26 | "summary_and_briefing_agent": agents.summary_and_briefing_agent(), 27 | } 28 | 29 | def _set_tasks(self): 30 | tasks = MeetingPreparationTasks() 31 | # Create Tasks 32 | research = tasks.research_task( 33 | self.agents["researcher_agent"], self.participants, self.context 34 | ) 35 | industry_analysis = tasks.industry_analysis_task( 36 | self.agents["industry_analyst_agent"], self.participants, self.context 37 | ) 38 | meeting_strategy = tasks.meeting_strategy_task( 39 | self.agents["meeting_strategy_agent"], self.context, self.objective 40 | ) 41 | summary_and_briefing = tasks.summary_and_briefing_task( 42 | self.agents["summary_and_briefing_agent"], self.context, self.objective 43 | ) 44 | self.tasks = [ 45 | research, 46 | industry_analysis, 47 | meeting_strategy, 48 | summary_and_briefing, 49 | ] 50 | -------------------------------------------------------------------------------- /taskforce/crews/meeting_prep/tasks.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Task 5 | 6 | verbose = bool(os.environ.get("VERBOSE", False)) 7 | 8 | 9 | class MeetingPreparationTasks: 10 | def research_task(self, agent, participants, context): 11 | return Task( 12 | description=dedent( 13 | f"""\ 14 | Conduct comprehensive research on each of the individuals and companies 15 | involved in the upcoming meeting. Gather information on recent 16 | news, achievements, professional background, and any relevant 17 | business activities. 18 | 19 | Participants: {participants} 20 | Meeting Context: {context}""" 21 | ), 22 | expected_output=dedent( 23 | """\ 24 | A detailed report summarizing key findings about each participant 25 | and company, highlighting information that could be relevant for the meeting.""" 26 | ), 27 | async_execution=True, 28 | agent=agent, 29 | ) 30 | 31 | def industry_analysis_task(self, agent, participants, context): 32 | return Task( 33 | description=dedent( 34 | f"""\ 35 | Analyze the current industry trends, challenges, and opportunities 36 | relevant to the meeting's context. Consider market reports, recent 37 | developments, and expert opinions to provide a comprehensive 38 | overview of the industry landscape. 39 | 40 | Participants: {participants} 41 | Meeting Context: {context}""" 42 | ), 43 | expected_output=dedent( 44 | """\ 45 | An insightful analysis that identifies major trends, potential 46 | challenges, and strategic opportunities.""" 47 | ), 48 | async_execution=True, 49 | agent=agent, 50 | ) 51 | 52 | def meeting_strategy_task(self, agent, context, objective): 53 | return Task( 54 | description=dedent( 55 | f"""\ 56 | Develop strategic talking points, questions, and discussion angles 57 | for the meeting based on the research and industry analysis conducted 58 | 59 | Meeting Context: {context} 60 | Meeting Objective: {objective}""" 61 | ), 62 | expected_output=dedent( 63 | """\ 64 | Complete report with a list of key talking points, strategic questions 65 | to ask to help achieve the meetings objective during the meeting.""" 66 | ), 67 | agent=agent, 68 | ) 69 | 70 | def summary_and_briefing_task(self, agent, context, objective): 71 | return Task( 72 | description=dedent( 73 | f"""\ 74 | Compile all the research findings, industry analysis, and strategic 75 | talking points into a concise, comprehensive briefing document for 76 | the meeting. 77 | Ensure the briefing is easy to digest and equips the meeting 78 | participants with all necessary information and strategies. 79 | 80 | Meeting Context: {context} 81 | Meeting Objective: {objective}""" 82 | ), 83 | expected_output=dedent( 84 | """\ 85 | A well-structured briefing document that includes sections for 86 | participant bios, industry overview, talking points, and 87 | strategic recommendations.""" 88 | ), 89 | agent=agent, 90 | ) 91 | -------------------------------------------------------------------------------- /taskforce/crews/meeting_prep/test_crew.py: -------------------------------------------------------------------------------- 1 | from crews.meeting_prep.crew import MeetingPrepCrew 2 | from lib.interfaces.TestInterface import TestCrewInterface 3 | 4 | 5 | class MeetingPrepTest(TestCrewInterface): 6 | participants = "uria franko, john doe, jane doe" 7 | context = "We meet to discuss the new product launch" 8 | objective = "To prepare for the upcoming product launch" 9 | 10 | def init_class(self): 11 | crew = MeetingPrepCrew( 12 | participants=self.participants, context=self.context, objective=self.objective 13 | ) 14 | return crew 15 | 16 | def test_crew_company(self): 17 | crew = self.init_class() 18 | assert crew.participants == self.participants 19 | assert crew.context == self.context 20 | assert crew.objective == self.objective 21 | 22 | def test_crew_agents(self): 23 | crew = self.init_class() 24 | assert len(crew.agents) > 0 25 | 26 | def test_crew_tasks(self): 27 | crew = self.init_class() 28 | assert len(crew.tasks) > 0 29 | -------------------------------------------------------------------------------- /taskforce/crews/product_photographer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/product_photographer/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/product_photographer/agents.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent 5 | 6 | from lib.tools.browser_tools import BrowserTools 7 | from lib.tools.search_tools import SearchTools 8 | 9 | verbose = bool(os.environ.get("VERBOSE", False)) 10 | 11 | 12 | class ProductPhotographerAgents: 13 | def senior_product_photographer_agent(self): 14 | return Agent( 15 | role="Senior Product Photographer", 16 | goal=dedent( 17 | """\ 18 | Take the most amazing photographs for instagram ads that 19 | capture emotions and convey a compelling message.""" 20 | ), 21 | backstory=dedent( 22 | """\ 23 | As a Senior Photographer at a leading digital marketing 24 | agency, you are an expert at taking amazing photographs that 25 | inspire and engage, you're now working on a new campaign for a super 26 | important customer and you need to take the most amazing photograph.""" 27 | ), 28 | tools=[ 29 | BrowserTools.scrape_and_summarize_website, 30 | SearchTools.search_internet, 31 | SearchTools.search_instagram, 32 | ], 33 | verbose=verbose, 34 | ) 35 | -------------------------------------------------------------------------------- /taskforce/crews/product_photographer/crew.py: -------------------------------------------------------------------------------- 1 | from crews.product_photographer.agents import ProductPhotographerAgents 2 | from crews.product_photographer.tasks import ProductPhotographerTasks 3 | from lib.interfaces.CrewManager import CrewManager 4 | 5 | 6 | class ProductPhotographerCrew(CrewManager): 7 | """ 8 | Crew for product photography, 9 | Given a copy, product website and product details, 10 | the crew will generate text-2-image paragraphs for the copy 11 | """ 12 | 13 | def __init__(self, copy: str, product_website: str, product_details: str): 14 | self.copy = copy 15 | self.product_website = product_website 16 | self.product_details = product_details 17 | 18 | super().__init__() 19 | 20 | def _set_agents(self): 21 | agents = ProductPhotographerAgents() 22 | self.agents = { 23 | "senior_photographer_agent": agents.senior_product_photographer_agent(), 24 | } 25 | 26 | def _set_tasks(self): 27 | tasks = ProductPhotographerTasks() 28 | self.tasks = [ 29 | tasks.product_photograph_task( 30 | self.agents["senior_photographer_agent"], 31 | self.copy, 32 | self.product_website, 33 | self.product_details, 34 | ) 35 | ] 36 | -------------------------------------------------------------------------------- /taskforce/crews/product_photographer/tasks.py: -------------------------------------------------------------------------------- 1 | from textwrap import dedent 2 | 3 | from crewai import Task 4 | 5 | 6 | class ProductPhotographerTasks: 7 | def product_photograph_task(self, agent, copy, product_website, product_details): 8 | return Task( 9 | description=dedent( 10 | f"""\ 11 | You are working on a new campaign for a super important customer, 12 | and you MUST take the most amazing photo ever for an instagram post 13 | regarding the product, you have the following copy: 14 | {copy} 15 | 16 | This is the product you are working with: {product_website}. 17 | Extra details provided by the customer: {product_details}. 18 | 19 | Imagine what the photo you wanna take describe it in a paragraph. 20 | Here are some examples for you follow: 21 | - high tech airplane in a beautiful blue sky in a beautiful sunset super crispy beautiful 4k, professional wide shot 22 | - the last supper, with Jesus and his disciples, breaking bread, close shot, soft lighting, 4k, crisp 23 | - an bearded old man in the snows, using very warm clothing, with mountains full of snow behind him, soft lighting, 4k, crisp, close up to the camera 24 | 25 | Think creatively and focus on how the image can capture the audience's 26 | attention. Don't show the actual product on the photo. 27 | 28 | Your final answer must be 3 options of photographs, each with 1 paragraph 29 | describing the photograph exactly like the examples provided above. 30 | """ # noqa: E501 31 | ), 32 | agent=agent, 33 | ) 34 | 35 | def product_review_photo(self, agent, product_website, product_details): 36 | return Task( 37 | description=dedent( 38 | f"""\ 39 | Review the photos you got from the senior photographer. 40 | Make sure it's the best possible and aligned with the product's goals, 41 | review, approve, ask clarifying question or delegate follow up work if 42 | necessary to make decisions. When delegating work send the full draft 43 | as part of the information. 44 | 45 | This is the product you are working with: {product_website}. 46 | Extra details provided by the customer: {product_details}. 47 | 48 | Here are some examples on how the final photographs should look like: 49 | - high tech airplane in a beautiful blue sky in a beautiful sunset super crispy beautiful 4k, professional wide shot 50 | - the last supper, with Jesus and his disciples, breaking bread, close shot, soft lighting, 4k, crisp 51 | - an bearded old man in the snows, using very warm clothing, with mountains full of snow behind him, soft lighting, 4k, crisp, close up to the camera 52 | 53 | Your final answer must be 3 reviewed options of photographs, 54 | each with 1 paragraph description following the examples provided above. 55 | """ # noqa: E501 56 | ), 57 | agent=agent, 58 | ) 59 | -------------------------------------------------------------------------------- /taskforce/crews/product_photographer/test_crew.py: -------------------------------------------------------------------------------- 1 | from crews.product_photographer.crew import ProductPhotographerCrew 2 | from lib.interfaces.TestInterface import TestCrewInterface 3 | 4 | 5 | class ProductPhotographerTest(TestCrewInterface): 6 | copy = "Today is a good day!" 7 | product_details = "This is a product description" 8 | product_website = "www.productwebsite.com" 9 | 10 | def init_class(self): 11 | crew = ProductPhotographerCrew( 12 | copy=self.copy, 13 | product_details=self.product_details, 14 | product_website=self.product_website, 15 | ) 16 | return crew 17 | 18 | def test_crew_company(self): 19 | crew = self.init_class() 20 | assert crew.copy == self.copy 21 | assert crew.product_details == self.product_details 22 | assert crew.product_website == self.product_website 23 | 24 | def test_crew_agents(self): 25 | crew = self.init_class() 26 | assert len(crew.agents) > 0 27 | 28 | def test_crew_tasks(self): 29 | crew = self.init_class() 30 | assert len(crew.tasks) > 0 31 | -------------------------------------------------------------------------------- /taskforce/crews/stock_analysis/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/stock_analysis/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/stock_analysis/agents.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent 5 | from langchain.tools.yahoo_finance_news import YahooFinanceNewsTool 6 | 7 | from lib.tools.browser_tools import BrowserTools 8 | from lib.tools.calculator_tools import CalculatorTools 9 | from lib.tools.search_tools import SearchTools 10 | from lib.tools.sec_tools import SECTools 11 | 12 | verbose = bool(os.environ.get("VERBOSE", False)) 13 | 14 | 15 | class StockAnalysisAgents: 16 | def financial_analyst(self): 17 | return Agent( 18 | role="The Best Financial Analyst", 19 | goal=dedent( 20 | """Impress all customers with your financial data 21 | and market trends analysis""" 22 | ), 23 | backstory=dedent( 24 | """The most seasoned financial analyst with 25 | lots of expertise in stock market analysis and investment 26 | strategies that is working for a super important customer.""" 27 | ), 28 | verbose=verbose, 29 | tools=[ 30 | BrowserTools.scrape_and_summarize_website, 31 | SearchTools.search_internet, 32 | CalculatorTools.calculate, 33 | SECTools.search_10q, 34 | SECTools.search_10k, 35 | ], 36 | ) 37 | 38 | def research_analyst(self): 39 | return Agent( 40 | role="Staff Research Analyst", 41 | goal=dedent( 42 | """Being the best at gather, interpret data and amaze 43 | your customer with it""" 44 | ), 45 | backstory=dedent( 46 | """Known as the BEST research analyst, you're 47 | skilled in sifting through news, company announcements, 48 | and market sentiments. Now you're working on a super 49 | important customer""" 50 | ), 51 | verbose=verbose, 52 | tools=[ 53 | BrowserTools.scrape_and_summarize_website, 54 | SearchTools.search_internet, 55 | SearchTools.search_news, 56 | YahooFinanceNewsTool(), 57 | SECTools.search_10q, 58 | SECTools.search_10k, 59 | ], 60 | ) 61 | 62 | def investment_advisor(self): 63 | return Agent( 64 | role="Private Investment Advisor", 65 | goal=dedent( 66 | """Impress your customers with full analyses over stocks 67 | and completer investment recommendations""" 68 | ), 69 | backstory=dedent( 70 | """You're the most experienced investment advisor 71 | and you combine various analytical insights to formulate 72 | strategic investment advice. You are now working for 73 | a super important customer you need to impress.""" 74 | ), 75 | verbose=verbose, 76 | tools=[ 77 | BrowserTools.scrape_and_summarize_website, 78 | SearchTools.search_internet, 79 | SearchTools.search_news, 80 | CalculatorTools.calculate, 81 | YahooFinanceNewsTool(), 82 | ], 83 | ) 84 | -------------------------------------------------------------------------------- /taskforce/crews/stock_analysis/crew.py: -------------------------------------------------------------------------------- 1 | from crews.stock_analysis.agents import StockAnalysisAgents 2 | from crews.stock_analysis.tasks import StockAnalysisTasks 3 | from lib.interfaces.CrewManager import CrewManager 4 | 5 | 6 | class StockAnalysisCrew(CrewManager): 7 | """ 8 | Crew for financial analysis, 9 | Given a company, 10 | the crew will run a financial analysis on the company and provide a report 11 | """ 12 | 13 | def __init__(self, company): 14 | self.company = company 15 | 16 | super().__init__() 17 | 18 | def _set_agents(self): 19 | agents = StockAnalysisAgents() 20 | self.agents = { 21 | "research_analyst": agents.research_analyst(), 22 | "financial_analyst": agents.financial_analyst(), 23 | } 24 | 25 | def _set_tasks(self): 26 | tasks = StockAnalysisTasks() 27 | self.tasks = [ 28 | tasks.research(self.agents["research_analyst"], self.company), 29 | tasks.financial_analysis(self.agents["financial_analyst"]), 30 | ] 31 | -------------------------------------------------------------------------------- /taskforce/crews/stock_analysis/tasks.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Task 5 | 6 | verbose = bool(os.environ.get("VERBOSE", False)) 7 | 8 | 9 | class StockAnalysisTasks: 10 | def research(self, agent, company): 11 | return Task( 12 | description=dedent( 13 | f""" 14 | Collect and summarize recent news articles, press 15 | releases, and market analyses related to the stock and 16 | its industry. 17 | Pay special attention to any significant events, market 18 | sentiments, and analysts' opinions. Also include upcoming 19 | events like earnings and others. 20 | 21 | Your final answer MUST be a report that includes a 22 | comprehensive summary of the latest news, any notable 23 | shifts in market sentiment, and potential impacts on 24 | the stock. 25 | Also make sure to return the stock ticker. 26 | 27 | {self.__tip_section()} 28 | 29 | Make sure to use the most recent data as possible. 30 | 31 | Selected company by the customer: {company} 32 | """ 33 | ), 34 | agent=agent, 35 | ) 36 | 37 | def financial_analysis(self, agent): 38 | return Task( 39 | description=dedent( 40 | f""" 41 | Conduct a thorough analysis of the stock's financial 42 | health and market performance. 43 | This includes examining key financial metrics such as 44 | P/E ratio, EPS growth, revenue trends, and 45 | debt-to-equity ratio. 46 | Also, analyze the stock's performance in comparison 47 | to its industry peers and overall market trends. 48 | 49 | Your final report MUST expand on the summary provided 50 | but now including a clear assessment of the stock's 51 | financial standing, its strengths and weaknesses, 52 | and how it fares against its competitors in the current 53 | market scenario. 54 | 55 | {self.__tip_section()} 56 | 57 | Make sure to use the most recent data possible. 58 | """ 59 | ), 60 | agent=agent, 61 | ) 62 | 63 | def filings_analysis(self, agent): 64 | return Task( 65 | description=dedent( 66 | f""" 67 | Analyze the latest 10-Q and 10-K filings from EDGAR for 68 | the stock in question. 69 | Focus on key sections like Management's Discussion and 70 | Analysis, financial statements, insider trading activity, 71 | and any disclosed risks. 72 | Extract relevant data and insights that could influence 73 | the stock's future performance. 74 | 75 | Your final answer must be an expanded report that now 76 | also highlights significant findings from these filings, 77 | including any red flags or positive indicators for 78 | your customer. 79 | {self.__tip_section()} 80 | """ 81 | ), 82 | agent=agent, 83 | ) 84 | 85 | def recommend(self, agent): 86 | return Task( 87 | description=dedent( 88 | f""" 89 | Review and synthesize the analyses provided by the 90 | Financial Analyst and the Research Analyst. 91 | Combine these insights to form a comprehensive 92 | investment recommendation. 93 | 94 | You MUST Consider all aspects, including financial 95 | health, market sentiment, and qualitative data from 96 | EDGAR filings. 97 | 98 | Make sure to include a section that shows insider 99 | trading activity, and upcoming events like earnings. 100 | 101 | Your final answer MUST be a recommendation for your 102 | customer. It should be a full super detailed report, providing a 103 | clear investment stance and strategy with supporting evidence. 104 | Make it pretty and well formatted for your customer. 105 | {self.__tip_section()} 106 | """ 107 | ), 108 | agent=agent, 109 | ) 110 | 111 | def __tip_section(self): 112 | return "If you do your BEST WORK, I'll give you a $10,000 commission!" 113 | -------------------------------------------------------------------------------- /taskforce/crews/stock_analysis/test_crew.py: -------------------------------------------------------------------------------- 1 | from crews.stock_analysis.crew import StockAnalysisCrew 2 | from lib.interfaces.TestInterface import TestCrewInterface 3 | 4 | 5 | class StockAnalysisTest(TestCrewInterface): 6 | crew_class = StockAnalysisCrew 7 | 8 | company_name = "Apple Inc." 9 | 10 | def init_class(self): 11 | self.crew_class(self.company_name) 12 | 13 | def test_crew_company(self): 14 | crew = self.crew_class(self.company_name) 15 | assert crew.company == self.company_name 16 | 17 | def test_crew_agents(self): 18 | crew = self.crew_class(self.company_name) 19 | assert len(crew.agents) > 0 20 | 21 | def test_crew_tasks(self): 22 | crew = self.crew_class(self.company_name) 23 | assert len(crew.tasks) > 0 24 | -------------------------------------------------------------------------------- /taskforce/crews/template_crew/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/template_crew/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/template_crew/agents.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent 5 | 6 | from lib.tools.search_tools import SearchTools 7 | 8 | verbose = bool(os.environ.get("VERBOSE", False)) 9 | 10 | 11 | class TemplateAgents: 12 | def template_agent(self): 13 | return Agent( 14 | role="You're a template agent", 15 | goal=dedent("""Tell me you're an agent that does something amazing."""), 16 | backstory=dedent( 17 | """\ 18 | Tell me about your backstory. What makes you the best at what you do? 19 | """ 20 | ), 21 | verbose=verbose, 22 | tools=[ 23 | SearchTools.search_internet, 24 | ], 25 | ) 26 | -------------------------------------------------------------------------------- /taskforce/crews/template_crew/crew.py: -------------------------------------------------------------------------------- 1 | from crews.template_crew.agents import TemplateAgents 2 | from crews.template_crew.tasks import TemplateTasks 3 | from lib.interfaces.CrewManager import CrewManager 4 | 5 | 6 | class TemplateCrew(CrewManager): 7 | """ 8 | Crew for as a template, 9 | Given an example, 10 | the crew will say it can't do anything. 11 | """ 12 | 13 | def __init__(self, example: str): 14 | self.example = example 15 | 16 | super().__init__() 17 | 18 | def _set_agents(self): 19 | agents = TemplateAgents() 20 | self.agents = { 21 | "template_agent": agents.template_agent(), 22 | } 23 | 24 | def _set_tasks(self): 25 | tasks = TemplateTasks() 26 | self.tasks = [ 27 | tasks.say_nothing(self.agents["template_agent"]), 28 | ] 29 | -------------------------------------------------------------------------------- /taskforce/crews/template_crew/tasks.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent, Task 5 | 6 | verbose = bool(os.environ.get("VERBOSE", False)) 7 | 8 | 9 | class TemplateTasks: 10 | def say_nothing(self, agent: Agent): 11 | return Task( 12 | description=dedent( 13 | f""" 14 | Tell the user that you are just an agent and you can't do anything. 15 | {self.__tip_section()} 16 | """ 17 | ), 18 | agent=agent, 19 | ) 20 | 21 | def __tip_section(self): 22 | return "If you do your BEST WORK, I'll give you a $10,000 commission!" 23 | -------------------------------------------------------------------------------- /taskforce/crews/template_crew/test_crew.py: -------------------------------------------------------------------------------- 1 | from crews.stock_analysis.crew import StockAnalysisCrew 2 | from lib.interfaces.TestInterface import TestCrewInterface 3 | 4 | 5 | class StockAnalysisTest(TestCrewInterface): 6 | crew_class = StockAnalysisCrew 7 | 8 | company_name = "Apple Inc." 9 | 10 | def init_class(self): 11 | self.crew_class(self.company_name) 12 | 13 | def test_crew_company(self): 14 | crew = self.crew_class(self.company_name) 15 | assert crew.company == self.company_name 16 | 17 | def test_crew_agents(self): 18 | crew = self.crew_class(self.company_name) 19 | assert len(crew.agents) > 0 20 | 21 | def test_crew_tasks(self): 22 | crew = self.crew_class(self.company_name) 23 | assert len(crew.tasks) > 0 24 | -------------------------------------------------------------------------------- /taskforce/crews/trip_planner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/crews/trip_planner/__init__.py -------------------------------------------------------------------------------- /taskforce/crews/trip_planner/agents.py: -------------------------------------------------------------------------------- 1 | import os 2 | from textwrap import dedent 3 | 4 | from crewai import Agent 5 | 6 | from lib.tools.browser_tools import BrowserTools 7 | from lib.tools.calculator_tools import CalculatorTools 8 | from lib.tools.search_tools import SearchTools 9 | 10 | verbose = bool(os.environ.get("VERBOSE", False)) 11 | 12 | 13 | class TripAgents: 14 | def city_selection_agent(self): 15 | return Agent( 16 | role="City Selection Expert", 17 | goal="Select the best city based on weather, season, and prices", 18 | backstory="An expert in analyzing travel data to pick ideal destinations", 19 | tools=[ 20 | SearchTools.search_internet, 21 | BrowserTools.scrape_and_summarize_website, 22 | ], 23 | verbose=verbose, 24 | ) 25 | 26 | def local_expert(self): 27 | return Agent( 28 | role="Local Expert at this city", 29 | goal="Provide the BEST insights about the selected city", 30 | backstory="""A knowledgeable local guide with extensive information 31 | about the city, it's attractions and customs""", 32 | tools=[ 33 | SearchTools.search_internet, 34 | BrowserTools.scrape_and_summarize_website, 35 | ], 36 | verbose=verbose, 37 | ) 38 | 39 | def travel_concierge(self): 40 | return Agent( 41 | role="Amazing Travel Concierge", 42 | goal=dedent( 43 | """Create the most amazing travel itineraries with budget and 44 | packing suggestions for the city""" 45 | ), 46 | backstory=dedent( 47 | """Specialist in travel planning and logistics with 48 | decades of experience""" 49 | ), 50 | tools=[ 51 | SearchTools.search_internet, 52 | BrowserTools.scrape_and_summarize_website, 53 | CalculatorTools.calculate, 54 | ], 55 | verbose=verbose, 56 | ) 57 | -------------------------------------------------------------------------------- /taskforce/crews/trip_planner/crew.py: -------------------------------------------------------------------------------- 1 | from crews.trip_planner.agents import TripAgents 2 | from crews.trip_planner.tasks import TripTasks 3 | from lib.interfaces.CrewManager import CrewManager 4 | 5 | 6 | class TripPlannerCrew(CrewManager): 7 | """ 8 | Crew for trip planning, 9 | Given a city, interests, and date range, 10 | the crew will plan a trip for the user to the city with the given interests 11 | using local experts and travel concierge 12 | """ 13 | 14 | def __init__(self, origin: str, cities: str, date_range: str, interests: str): 15 | self.cities = cities 16 | self.origin = origin 17 | self.interests = interests 18 | self.date_range = date_range 19 | 20 | super().__init__() 21 | 22 | def _set_agents(self): 23 | agents = TripAgents() 24 | self.agents = { 25 | "city_selection_agent": agents.city_selection_agent(), 26 | "local_expert": agents.local_expert(), 27 | "travel_concierge": agents.travel_concierge(), 28 | } 29 | 30 | def _set_tasks(self): 31 | tasks = TripTasks() 32 | self.tasks = [ 33 | tasks.identify_task( 34 | self.agents["city_selection_agent"], 35 | self.origin, 36 | self.cities, 37 | self.interests, 38 | self.date_range, 39 | ), 40 | tasks.gather_task( 41 | self.agents["local_expert"], self.origin, self.interests, self.date_range 42 | ), 43 | tasks.plan_task( 44 | self.agents["travel_concierge"], self.origin, self.interests, self.date_range 45 | ), 46 | ] 47 | -------------------------------------------------------------------------------- /taskforce/crews/trip_planner/tasks.py: -------------------------------------------------------------------------------- 1 | from textwrap import dedent 2 | 3 | from crewai import Task 4 | 5 | 6 | class TripTasks: 7 | def identify_task(self, agent, origin, cities, interests, range): 8 | return Task( 9 | description=dedent( 10 | f""" 11 | Analyze and select the best city for the trip based 12 | on specific criteria such as weather patterns, seasonal 13 | events, and travel costs. This task involves comparing 14 | multiple cities, considering factors like current weather 15 | conditions, upcoming cultural or seasonal events, and 16 | overall travel expenses. 17 | 18 | Your final answer must be a detailed 19 | report on the chosen city, and everything you found out 20 | about it, including the actual flight costs, weather 21 | forecast and attractions. 22 | {self.__tip_section()} 23 | 24 | Traveling from: {origin} 25 | City Options: {cities} 26 | Trip Date: {range} 27 | Traveler Interests: {interests} 28 | """ 29 | ), 30 | agent=agent, 31 | ) 32 | 33 | def gather_task(self, agent, origin, interests, range): 34 | return Task( 35 | description=dedent( 36 | f""" 37 | As a local expert on this city you must compile an 38 | in-depth guide for someone traveling there and wanting 39 | to have THE BEST trip ever! 40 | Gather information about key attractions, local customs, 41 | special events, and daily activity recommendations. 42 | Find the best spots to go to, the kind of place only a 43 | local would know. 44 | This guide should provide a thorough overview of what 45 | the city has to offer, including hidden gems, cultural 46 | hotspots, must-visit landmarks, weather forecasts, and 47 | high level costs. 48 | 49 | The final answer must be a comprehensive city guide, 50 | rich in cultural insights and practical tips, 51 | tailored to enhance the travel experience. 52 | {self.__tip_section()} 53 | 54 | Trip Date: {range} 55 | Traveling from: {origin} 56 | Traveler Interests: {interests} 57 | """ 58 | ), 59 | agent=agent, 60 | ) 61 | 62 | def plan_task(self, agent, origin, interests, range): 63 | return Task( 64 | description=dedent( 65 | f""" 66 | Expand this guide into a a full 7-day travel 67 | itinerary with detailed per-day plans, including 68 | weather forecasts, places to eat, packing suggestions, 69 | and a budget breakdown. 70 | 71 | You MUST suggest actual places to visit, actual hotels 72 | to stay and actual restaurants to go to. 73 | 74 | This itinerary should cover all aspects of the trip, 75 | from arrival to departure, integrating the city guide 76 | information with practical travel logistics. 77 | 78 | Your final answer MUST be a complete expanded travel plan, 79 | formatted as markdown, encompassing a daily schedule, 80 | anticipated weather conditions, recommended clothing and 81 | items to pack, and a detailed budget, ensuring THE BEST 82 | TRIP EVER, Be specific and give it a reason why you picked 83 | # up each place, what make them special! {self.__tip_section()} 84 | 85 | Trip Date: {range} 86 | Traveling from: {origin} 87 | Traveler Interests: {interests} 88 | """ 89 | ), 90 | agent=agent, 91 | ) 92 | 93 | def __tip_section(self): 94 | return "If you do your BEST WORK, I'll tip you $100!" 95 | -------------------------------------------------------------------------------- /taskforce/crews/trip_planner/test_crew.py: -------------------------------------------------------------------------------- 1 | from crews.trip_planner.crew import TripPlannerCrew 2 | from lib.interfaces.TestInterface import TestCrewInterface 3 | 4 | 5 | class TripPlannerTest(TestCrewInterface): 6 | origin = "San Francisco" 7 | cities = "New York" 8 | date_range = "2024-01-01 - 2024-01-07" 9 | interests = "museums, parks, restaurants, shopping" 10 | 11 | def init_class(self): 12 | crew = TripPlannerCrew( 13 | origin=self.origin, 14 | cities=self.cities, 15 | date_range=self.date_range, 16 | interests=self.interests, 17 | ) 18 | return crew 19 | 20 | def test_crew_company(self): 21 | crew = self.init_class() 22 | assert crew.origin == self.origin 23 | assert crew.cities == self.cities 24 | assert crew.date_range == self.date_range 25 | assert crew.interests == self.interests 26 | 27 | def test_crew_agents(self): 28 | crew = self.init_class() 29 | assert len(crew.agents) > 0 30 | 31 | def test_crew_tasks(self): 32 | crew = self.init_class() 33 | assert len(crew.tasks) > 0 34 | -------------------------------------------------------------------------------- /taskforce/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/lib/__init__.py -------------------------------------------------------------------------------- /taskforce/lib/interfaces/CrewManager.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from textwrap import dedent 3 | 4 | from crewai import Agent, Crew, Task 5 | 6 | 7 | class CrewManager(ABC): 8 | """ 9 | CrewManager is an abstract class that provides a blueprint for creating a Crew. 10 | """ 11 | 12 | crew: Crew 13 | agents: dict[str, Agent] 14 | tasks: list[Task] 15 | 16 | def __init__(self): 17 | self._set_agents() 18 | self._set_tasks() 19 | 20 | def run(self): 21 | # check if agents are created and in right type 22 | if not isinstance(self.agents, dict) or len(self.agents.items()) < 1: 23 | raise Exception("Agents not created") 24 | if not isinstance(self.tasks, list) or len(self.tasks) < 1: 25 | raise Exception("Tasks not created") 26 | 27 | crew = Crew(agents=list(self.agents.values()), tasks=self.tasks) 28 | return crew.kickoff() 29 | 30 | @abstractmethod 31 | def _set_agents(cls): 32 | pass 33 | 34 | @abstractmethod 35 | def _set_tasks(cls): 36 | pass 37 | 38 | @property 39 | def description(self): 40 | if not self.__doc__: 41 | return "No description provided" 42 | 43 | return dedent( 44 | f"""\ 45 | {self.__doc__} 46 | Agent names: {', '.join(self.agents.keys())} 47 | """ 48 | ) 49 | -------------------------------------------------------------------------------- /taskforce/lib/interfaces/TestInterface.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from load_dotenv import load_dotenv 4 | 5 | from lib.interfaces.CrewManager import CrewManager 6 | 7 | load_dotenv() 8 | 9 | 10 | class TestCrewInterface(unittest.TestCase): 11 | crew_class = CrewManager 12 | 13 | def init_class(self): 14 | pass 15 | 16 | def test_crew_agents(self): 17 | pass 18 | 19 | def test_crew_tasks(self): 20 | pass 21 | -------------------------------------------------------------------------------- /taskforce/lib/interfaces/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/lib/interfaces/__init__.py -------------------------------------------------------------------------------- /taskforce/lib/models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class ToolInitiator(BaseModel): 5 | path: str 6 | name: str 7 | description: str 8 | -------------------------------------------------------------------------------- /taskforce/lib/tasks_utils.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | 3 | from langchain.agents import Tool 4 | 5 | from lib.models import ToolInitiator 6 | 7 | 8 | def dynamic_import(attr_path: str): 9 | """ 10 | Dynamically imports an attribute (e.g., a class or function) 11 | from a given path. 12 | 13 | Parameters: 14 | - attr_path (str): The full path to the attribute, 15 | formatted as 'module.submodule:AttributeName'. 16 | 17 | Returns: 18 | - The imported attribute. 19 | """ 20 | if attr_path.startswith("from "): 21 | attr_path = attr_path.replace("from ", "") 22 | 23 | module_path, attr_name = attr_path.split(" import ") 24 | module = importlib.import_module(module_path) 25 | return getattr(module, attr_name) 26 | 27 | 28 | def tool_initiator(tool_config: ToolInitiator): 29 | """ 30 | Initializes a tool by dynamically importing the tool's 31 | class and calling 32 | its `init` method. 33 | """ 34 | tool = dynamic_import(tool_config.path) 35 | return Tool( 36 | name=tool_config.name, 37 | func=tool.run, 38 | description=tool_config.description, 39 | ) 40 | -------------------------------------------------------------------------------- /taskforce/lib/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/lib/tools/__init__.py -------------------------------------------------------------------------------- /taskforce/lib/tools/browser_tools.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from textwrap import dedent 4 | 5 | import requests 6 | from crewai import Agent, Task 7 | from langchain.tools import tool 8 | from unstructured.partition.html import partition_html 9 | 10 | 11 | class BrowserTools: 12 | @staticmethod 13 | def needed_env_vars(): 14 | return ["BROWSERLESS_API_KEY"] 15 | 16 | @tool("Scrape website content") 17 | @staticmethod 18 | def scrape_and_summarize_website(website, use_browserless=False): 19 | """Useful to scrape and summarize a website content""" 20 | if use_browserless: 21 | response = browserless(website) 22 | else: 23 | response = requests.get(website) 24 | elements = partition_html(text=response.text) 25 | content = "\n\n".join([str(el) for el in elements]) 26 | content = [content[i : i + 8000] for i in range(0, len(content), 8000)] 27 | summaries = [] 28 | for chunk in content: 29 | agent = Agent( 30 | role="Principal Researcher", 31 | goal=dedent( 32 | """Do amazing research and summaries 33 | based on the content you are working with""" 34 | ), 35 | backstory=dedent( 36 | """You're a Principal Researcher at a big company 37 | and you need to do research about a given topic.""" 38 | ), 39 | allow_delegation=False, 40 | ) 41 | task = Task( 42 | agent=agent, 43 | description=dedent( 44 | f"""Analyze and summarize the content below, 45 | make sure to include the most relevant information in the summary, 46 | return only the summary nothing else. 47 | \n\nCONTENT\n----------\n{chunk}""" 48 | ), 49 | ) 50 | summary = task.execute() 51 | summaries.append(summary) 52 | return "\n\n".join(summaries) 53 | 54 | @tool("Scrape website content using browserless") 55 | @staticmethod 56 | def scrape_and_summarize_website_browserless(website): 57 | """Useful to scrape and summarize a website content using browserless""" 58 | return BrowserTools.scrape_and_summarize_website(website, use_browserless=True) 59 | 60 | 61 | def browserless(website): 62 | url = f"https://chrome.browserless.io/content?token={os.environ['BROWSERLESS_API_KEY']}" 63 | payload = json.dumps({"url": website}) 64 | headers = { 65 | "cache-control": "no-cache", 66 | "content-type": "application/json", 67 | } 68 | return requests.request("POST", url, headers=headers, data=payload) 69 | -------------------------------------------------------------------------------- /taskforce/lib/tools/calculator_tools.py: -------------------------------------------------------------------------------- 1 | from langchain.tools import tool 2 | 3 | 4 | class CalculatorTools: 5 | @staticmethod 6 | @tool("Make a calculation") 7 | def calculate(operation): 8 | """Useful to perform any mathematical calculations, 9 | like sum, minus, multiplication, division, etc. 10 | The input to this tool should be a mathematical 11 | expression, a couple examples are `200*7` or `5000/2*10` 12 | """ 13 | return eval(operation) 14 | -------------------------------------------------------------------------------- /taskforce/lib/tools/exa_search_tools.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from exa_py.api import Exa 4 | from langchain.agents import tool 5 | 6 | 7 | class ExaSearchTool: 8 | @staticmethod 9 | def needed_env_vars(): 10 | return ["EXA_API_KEY"] 11 | 12 | @tool 13 | @staticmethod 14 | def search(query: str): 15 | """Search for a webpage based on the query.""" 16 | return ExaSearchTool._exa().search(f"{query}", use_autoprompt=True, num_results=3) 17 | 18 | @tool 19 | @staticmethod 20 | def find_similar(url: str): 21 | """Search for webpages similar to a given URL. 22 | The url passed in should be a URL returned from `search`. 23 | """ 24 | return ExaSearchTool._exa().find_similar(url, num_results=3) 25 | 26 | @tool 27 | @staticmethod 28 | def get_contents(ids: str): 29 | """Get the contents of a webpage. 30 | The ids must be passed in as a list, a list of ids returned 31 | from `search`. 32 | """ 33 | ids = eval(ids) 34 | contents = str(ExaSearchTool._exa().get_contents(ids)) 35 | print(contents) 36 | contents = contents.split("URL:") 37 | contents = [content[:1000] for content in contents] 38 | return "\n\n".join(contents) 39 | 40 | @staticmethod 41 | def tools(): 42 | return [ 43 | ExaSearchTool.search, 44 | ExaSearchTool.find_similar, 45 | ExaSearchTool.get_contents, 46 | ] 47 | 48 | @staticmethod 49 | def _exa(): 50 | return Exa(api_key=os.environ["EXA_API_KEY"]) 51 | -------------------------------------------------------------------------------- /taskforce/lib/tools/search_tools.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | import requests 5 | from langchain.tools import tool 6 | 7 | 8 | class SearchTools: 9 | @staticmethod 10 | def needed_env_vars(): 11 | return ["SERPER_API_KEY"] 12 | 13 | @tool("Search the internet") 14 | @staticmethod 15 | def search_internet(query): 16 | """Useful to search the internet 17 | about a a given topic and return relevant results""" 18 | top_result_to_return = 4 19 | url = "https://google.serper.dev/search" 20 | payload = json.dumps({"q": query}) 21 | headers = { 22 | "X-API-KEY": os.environ["SERPER_API_KEY"], 23 | "content-type": "application/json", 24 | } 25 | response = requests.request("POST", url, headers=headers, data=payload) 26 | results = response.json()["organic"] 27 | string = [] 28 | for result in results[:top_result_to_return]: 29 | try: 30 | string.append( 31 | "\n".join( 32 | [ 33 | f"Title: {result['title']}", 34 | f"Link: {result['link']}", 35 | f"Snippet: {result['snippet']}", 36 | "\n-----------------", 37 | ] 38 | ) 39 | ) 40 | except KeyError: 41 | continue 42 | 43 | return "\n".join(string) 44 | 45 | @tool("Search news on the internet") 46 | @staticmethod 47 | def search_news(query): 48 | """Useful to search news about a company, stock or any other 49 | topic and return relevant results""" "" 50 | top_result_to_return = 4 51 | url = "https://google.serper.dev/news" 52 | payload = json.dumps({"q": query}) 53 | headers = { 54 | "X-API-KEY": os.environ["SERPER_API_KEY"], 55 | "content-type": "application/json", 56 | } 57 | response = requests.request("POST", url, headers=headers, data=payload) 58 | results = response.json()["news"] 59 | string = [] 60 | for result in results[:top_result_to_return]: 61 | try: 62 | string.append( 63 | "\n".join( 64 | [ 65 | f"Title: {result['title']}", 66 | f"Link: {result['link']}", 67 | f"Snippet: {result['snippet']}", 68 | "\n-----------------", 69 | ] 70 | ) 71 | ) 72 | except KeyError: 73 | continue 74 | 75 | return "\n".join(string) 76 | 77 | @tool("Search instagram") 78 | def search_instagram(query): 79 | """Useful to search for instagram post about a given topic and return relevant 80 | results.""" 81 | query = f"site:instagram.com {query}" 82 | return SearchTools.search_internet(query) 83 | -------------------------------------------------------------------------------- /taskforce/lib/tools/sec_tools.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import requests 4 | from langchain.text_splitter import CharacterTextSplitter 5 | from langchain.tools import tool 6 | from langchain_community.vectorstores import FAISS 7 | from langchain_openai import OpenAIEmbeddings 8 | from sec_api import QueryApi 9 | from unstructured.partition.html import partition_html 10 | 11 | 12 | class SECTools: 13 | @staticmethod 14 | def needed_env_vars(): 15 | return ["SEC_API_API_KEY"] 16 | 17 | @tool("Search 10-Q form") 18 | @staticmethod 19 | def search_10q(data): 20 | """ 21 | Useful to search information from the latest 10-Q form for a 22 | given stock. 23 | The input to this tool should be a pipe (|) separated text of 24 | length two, representing the stock ticker you are interested and what 25 | question you have from it. 26 | For example, `AAPL|what was last quarter's revenue`. 27 | """ 28 | stock, ask = data.split("|") 29 | queryApi = QueryApi(api_key=os.environ["SEC_API_API_KEY"]) 30 | query = { 31 | "query": {"query_string": {"query": f'ticker:{stock} AND formType:"10-Q"'}}, 32 | "from": "0", 33 | "size": "1", 34 | "sort": [{"filedAt": {"order": "desc"}}], 35 | } 36 | 37 | fillings = queryApi.get_filings(query)["filings"] 38 | if len(fillings) == 0: 39 | return ( 40 | "Sorry, I couldn't find any filling for this stock," 41 | " check if the ticker is correct." 42 | ) 43 | link = fillings[0]["linkToFilingDetails"] 44 | answer = SECTools.__embedding_search(link, ask) 45 | return answer 46 | 47 | @tool("Search 10-K form") 48 | @staticmethod 49 | def search_10k(data): 50 | """ 51 | Useful to search information from the latest 10-K form for a 52 | given stock. 53 | The input to this tool should be a pipe (|) separated text of 54 | length two, representing the stock ticker you are interested, what 55 | question you have from it. 56 | For example, `AAPL|what was last year's revenue`. 57 | """ 58 | stock, ask = data.split("|") 59 | queryApi = QueryApi(api_key=os.environ["SEC_API_API_KEY"]) 60 | query = { 61 | "query": {"query_string": {"query": f'ticker:{stock} AND formType:"10-K"'}}, 62 | "from": "0", 63 | "size": "1", 64 | "sort": [{"filedAt": {"order": "desc"}}], 65 | } 66 | 67 | fillings = queryApi.get_filings(query)["filings"] 68 | if len(fillings) == 0: 69 | return ( 70 | "Sorry, I couldn't find any filling for this stock," 71 | " check if the ticker is correct." 72 | ) 73 | link = fillings[0]["linkToFilingDetails"] 74 | answer = SECTools.__embedding_search(link, ask) 75 | return answer 76 | 77 | @staticmethod 78 | def __embedding_search(url, ask): 79 | text = SECTools.__download_form_html(url) 80 | elements = partition_html(text=text) 81 | content = "\n".join([str(el) for el in elements]) 82 | text_splitter = CharacterTextSplitter( 83 | separator="\n", 84 | chunk_size=1000, 85 | chunk_overlap=150, 86 | length_function=len, 87 | is_separator_regex=False, 88 | ) 89 | docs = text_splitter.create_documents([content]) 90 | retriever = FAISS.from_documents(docs, OpenAIEmbeddings()).as_retriever() 91 | answers = retriever.get_relevant_documents(ask, top_k=4) 92 | answers = "\n\n".join([a.page_content for a in answers]) 93 | return answers 94 | 95 | @staticmethod 96 | def __download_form_html(url): 97 | headers = { 98 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", # noqa 99 | "Accept-Encoding": "gzip, deflate, br", 100 | "Accept-Language": "en-US,en;q=0.9,pt-BR;q=0.8,pt;q=0.7", 101 | "Cache-Control": "max-age=0", 102 | "Dnt": "1", 103 | "Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120"', 104 | "Sec-Ch-Ua-Mobile": "?0", 105 | "Sec-Ch-Ua-Platform": '"macOS"', 106 | "Sec-Fetch-Dest": "document", 107 | "Sec-Fetch-Mode": "navigate", 108 | "Sec-Fetch-Site": "none", 109 | "Sec-Fetch-User": "?1", 110 | "Upgrade-Insecure-Requests": "1", 111 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", # noqa 112 | } 113 | 114 | response = requests.get(url, headers=headers) 115 | return response.text 116 | -------------------------------------------------------------------------------- /taskforce/lib/tools/utils.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uriafranko/TaskForce/46fead247bbb47daddffc3c990e6b58d3e22031c/taskforce/lib/tools/utils.py -------------------------------------------------------------------------------- /taskforce/main.py: -------------------------------------------------------------------------------- 1 | from load_dotenv import load_dotenv 2 | 3 | from crews.template_crew.crew import TemplateCrew 4 | 5 | load_dotenv() 6 | 7 | 8 | def main(): 9 | template_crew = TemplateCrew(example="I am an example") 10 | print(template_crew.description) 11 | print("Done!") 12 | 13 | 14 | if __name__ == "__main__": 15 | main() 16 | -------------------------------------------------------------------------------- /taskforce/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "taskforce" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Uria Franko "] 6 | readme = "README.md" 7 | 8 | [tool.poetry.dependencies] 9 | python = ">=3.10,<3.12" 10 | crewai = "^0.11.2" 11 | langchain = "^0.1.8" 12 | pydantic = "^2.6.1" 13 | unstructured = "^0.12.4" 14 | exa-py = "^1.0.8" 15 | sec-api = "^1.0.17" 16 | langchain-community = "^0.0.21" 17 | load-dotenv = "^0.1.0" 18 | yfinance = "^0.2.36" 19 | faiss-cpu = "^1.7.4" 20 | pytest-emoji = "^0.2.0" 21 | 22 | [tool.poetry.group.dev.dependencies] 23 | ruff = "^0.2.2" 24 | black = "^24.2.0" 25 | pre-commit = "^3.6.2" 26 | pytest = "^8.0.1" 27 | 28 | [build-system] 29 | requires = ["poetry-core"] 30 | build-backend = "poetry.core.masonry.api" 31 | 32 | 33 | [tool.ruff] 34 | line-length = 99 35 | indent-width = 4 36 | 37 | # Allow autofix for all enabled rules (when `--fix`) is provided. 38 | fixable = ["ALL"] 39 | unfixable = [] 40 | 41 | select = [ 42 | "E", # pycodestyle errors 43 | "W", # pycodestyle warnings 44 | "F", # pyflakes 45 | "I", # isort 46 | "B", # flake8-bugbear 47 | "C4", # flake8-comprehensions 48 | "UP", # pyupgrade 49 | ] 50 | 51 | ignore = [ 52 | "E501", # line too long, handled by black 53 | "B008", # do not perform function calls in argument defaults 54 | "W191", # indentation contains tabs 55 | ] 56 | target-version = "py310" 57 | 58 | 59 | [tool.ruff.pyupgrade] 60 | # Preserve types, even if a file imports `from __future__ import annotations`. 61 | keep-runtime-typing = true 62 | 63 | [tool.ruff.lint] 64 | 65 | select = [ 66 | "E", # pycodestyle errors 67 | "W", # pycodestyle warnings 68 | "F", # pyflakes 69 | "I", # isort 70 | "B", # flake8-bugbear 71 | "C4", # flake8-comprehensions 72 | "UP", # pyupgrade 73 | ] 74 | fixable = ["ALL"] 75 | unfixable = [] 76 | ignore = [] 77 | 78 | 79 | [tool.ruff.format] 80 | quote-style = "double" 81 | # docstring-code-format = true 82 | line-ending = "auto" 83 | skip-magic-trailing-comma = false 84 | 85 | 86 | [tool.pytest.ini_options] 87 | addopts = "--ignore=.venv/*" 88 | norecursedirs = ".venv" # This tells pytest not to enter these directories during collection 89 | filterwarnings = [ 90 | "ignore::Warning" # Too many warning from packages 91 | ] 92 | --------------------------------------------------------------------------------