├── .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 |

4 |
5 | # **TaskForce**
6 |
7 | 🤖 **TaskForce**: A community based framework around [CrewAi](https://crewai.com/) for collaborating AI agents.
8 |
9 | [](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 |
--------------------------------------------------------------------------------