mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-08 22:08:03 -05:00
added agents
This commit is contained in:
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.10
|
||||||
1
installer/client/cli/agents/.python-version
Normal file
1
installer/client/cli/agents/.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.10
|
||||||
81
installer/client/cli/agents/example.py
Normal file
81
installer/client/cli/agents/example.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
from langchain_community.tools import DuckDuckGoSearchRun
|
||||||
|
import os
|
||||||
|
from crewai import Agent, Task, Crew, Process
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
current_directory = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
config_directory = os.path.expanduser("~/.config/fabric")
|
||||||
|
env_file = os.path.join(config_directory, ".env")
|
||||||
|
load_dotenv(env_file)
|
||||||
|
os.environ['OPENAI_MODEL_NAME'] = 'gpt-4-0125-preview'
|
||||||
|
|
||||||
|
# You can choose to use a local model through Ollama for example. See https://docs.crewai.com/how-to/LLM-Connections/ for more information.
|
||||||
|
# osOPENAI_API_BASE='http://localhost:11434/v1'
|
||||||
|
# OPENAI_MODEL_NAME='openhermes' # Adjust based on available model
|
||||||
|
# OPENAI_API_KEY=''
|
||||||
|
|
||||||
|
# Install duckduckgo-search for this example:
|
||||||
|
# !pip install -U duckduckgo-search
|
||||||
|
|
||||||
|
search_tool = DuckDuckGoSearchRun()
|
||||||
|
|
||||||
|
# Define your agents with roles and goals
|
||||||
|
researcher = Agent(
|
||||||
|
role='Senior Research Analyst',
|
||||||
|
goal='Uncover cutting-edge developments in AI and data science',
|
||||||
|
backstory="""You work at a leading tech think tank.
|
||||||
|
Your expertise lies in identifying emerging trends.
|
||||||
|
You have a knack for dissecting complex data and presenting actionable insights.""",
|
||||||
|
verbose=True,
|
||||||
|
allow_delegation=False,
|
||||||
|
tools=[search_tool]
|
||||||
|
# You can pass an optional llm attribute specifying what mode you wanna use.
|
||||||
|
# It can be a local model through Ollama / LM Studio or a remote
|
||||||
|
# model like OpenAI, Mistral, Antrophic or others (https://docs.crewai.com/how-to/LLM-Connections/)
|
||||||
|
#
|
||||||
|
# import os
|
||||||
|
#
|
||||||
|
# OR
|
||||||
|
#
|
||||||
|
# from langchain_openai import ChatOpenAI
|
||||||
|
# llm=ChatOpenAI(model_name="gpt-3.5", temperature=0.7)
|
||||||
|
)
|
||||||
|
writer = Agent(
|
||||||
|
role='Tech Content Strategist',
|
||||||
|
goal='Craft compelling content on tech advancements',
|
||||||
|
backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles.
|
||||||
|
You transform complex concepts into compelling narratives.""",
|
||||||
|
verbose=True,
|
||||||
|
allow_delegation=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create tasks for your agents
|
||||||
|
task1 = Task(
|
||||||
|
description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024.
|
||||||
|
Identify key trends, breakthrough technologies, and potential industry impacts.""",
|
||||||
|
expected_output="Full analysis report in bullet points",
|
||||||
|
agent=researcher
|
||||||
|
)
|
||||||
|
|
||||||
|
task2 = Task(
|
||||||
|
description="""Using the insights provided, develop an engaging blog
|
||||||
|
post that highlights the most significant AI advancements.
|
||||||
|
Your post should be informative yet accessible, catering to a tech-savvy audience.
|
||||||
|
Make it sound cool, avoid complex words so it doesn't sound like AI.""",
|
||||||
|
expected_output="Full blog post of at least 4 paragraphs",
|
||||||
|
agent=writer
|
||||||
|
)
|
||||||
|
|
||||||
|
# Instantiate your crew with a sequential process
|
||||||
|
crew = Crew(
|
||||||
|
agents=[researcher, writer],
|
||||||
|
tasks=[task1, task2],
|
||||||
|
verbose=2, # You can set it to 1 or 2 to different logging levels
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get your crew to work!
|
||||||
|
result = crew.kickoff()
|
||||||
|
|
||||||
|
print("######################")
|
||||||
|
print(result)
|
||||||
89
installer/client/cli/agents/trip_planner/main.py
Normal file
89
installer/client/cli/agents/trip_planner/main.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
from crewai import Crew
|
||||||
|
from textwrap import dedent
|
||||||
|
from .trip_agents import TripAgents
|
||||||
|
from .trip_tasks import TripTasks
|
||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
current_directory = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
config_directory = os.path.expanduser("~/.config/fabric")
|
||||||
|
env_file = os.path.join(config_directory, ".env")
|
||||||
|
load_dotenv(env_file)
|
||||||
|
os.environ['OPENAI_MODEL_NAME'] = 'gpt-4-0125-preview'
|
||||||
|
|
||||||
|
|
||||||
|
class TripCrew:
|
||||||
|
|
||||||
|
def __init__(self, origin, cities, date_range, interests):
|
||||||
|
self.cities = cities
|
||||||
|
self.origin = origin
|
||||||
|
self.interests = interests
|
||||||
|
self.date_range = date_range
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
agents = TripAgents()
|
||||||
|
tasks = TripTasks()
|
||||||
|
|
||||||
|
city_selector_agent = agents.city_selection_agent()
|
||||||
|
local_expert_agent = agents.local_expert()
|
||||||
|
travel_concierge_agent = agents.travel_concierge()
|
||||||
|
|
||||||
|
identify_task = tasks.identify_task(
|
||||||
|
city_selector_agent,
|
||||||
|
self.origin,
|
||||||
|
self.cities,
|
||||||
|
self.interests,
|
||||||
|
self.date_range
|
||||||
|
)
|
||||||
|
gather_task = tasks.gather_task(
|
||||||
|
local_expert_agent,
|
||||||
|
self.origin,
|
||||||
|
self.interests,
|
||||||
|
self.date_range
|
||||||
|
)
|
||||||
|
plan_task = tasks.plan_task(
|
||||||
|
travel_concierge_agent,
|
||||||
|
self.origin,
|
||||||
|
self.interests,
|
||||||
|
self.date_range
|
||||||
|
)
|
||||||
|
|
||||||
|
crew = Crew(
|
||||||
|
agents=[
|
||||||
|
city_selector_agent, local_expert_agent, travel_concierge_agent
|
||||||
|
],
|
||||||
|
tasks=[identify_task, gather_task, plan_task],
|
||||||
|
verbose=True
|
||||||
|
)
|
||||||
|
|
||||||
|
result = crew.kickoff()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class planner_cli:
|
||||||
|
def ask(self):
|
||||||
|
print("## Welcome to Trip Planner Crew")
|
||||||
|
print('-------------------------------')
|
||||||
|
location = input(
|
||||||
|
dedent("""
|
||||||
|
From where will you be traveling from?
|
||||||
|
"""))
|
||||||
|
cities = input(
|
||||||
|
dedent("""
|
||||||
|
What are the cities options you are interested in visiting?
|
||||||
|
"""))
|
||||||
|
date_range = input(
|
||||||
|
dedent("""
|
||||||
|
What is the date range you are interested in traveling?
|
||||||
|
"""))
|
||||||
|
interests = input(
|
||||||
|
dedent("""
|
||||||
|
What are some of your high level interests and hobbies?
|
||||||
|
"""))
|
||||||
|
|
||||||
|
trip_crew = TripCrew(location, cities, date_range, interests)
|
||||||
|
result = trip_crew.run()
|
||||||
|
print("\n\n########################")
|
||||||
|
print("## Here is you Trip Plan")
|
||||||
|
print("########################\n")
|
||||||
|
print(result)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from crewai import Agent, Task
|
||||||
|
from langchain.tools import tool
|
||||||
|
from unstructured.partition.html import partition_html
|
||||||
|
|
||||||
|
|
||||||
|
class BrowserTools():
|
||||||
|
|
||||||
|
@tool("Scrape website content")
|
||||||
|
def scrape_and_summarize_website(website):
|
||||||
|
"""Useful to scrape and summarize a website content"""
|
||||||
|
url = f"https://chrome.browserless.io/content?token={os.environ['BROWSERLESS_API_KEY']}"
|
||||||
|
payload = json.dumps({"url": website})
|
||||||
|
headers = {'cache-control': 'no-cache', 'content-type': 'application/json'}
|
||||||
|
response = requests.request("POST", url, headers=headers, data=payload)
|
||||||
|
elements = partition_html(text=response.text)
|
||||||
|
content = "\n\n".join([str(el) for el in elements])
|
||||||
|
content = [content[i:i + 8000] for i in range(0, len(content), 8000)]
|
||||||
|
summaries = []
|
||||||
|
for chunk in content:
|
||||||
|
agent = Agent(
|
||||||
|
role='Principal Researcher',
|
||||||
|
goal=
|
||||||
|
'Do amazing researches and summaries based on the content you are working with',
|
||||||
|
backstory=
|
||||||
|
"You're a Principal Researcher at a big company and you need to do a research about a given topic.",
|
||||||
|
allow_delegation=False)
|
||||||
|
task = Task(
|
||||||
|
agent=agent,
|
||||||
|
description=
|
||||||
|
f'Analyze and summarize the content bellow, make sure to include the most relevant information in the summary, return only the summary nothing else.\n\nCONTENT\n----------\n{chunk}'
|
||||||
|
)
|
||||||
|
summary = task.execute()
|
||||||
|
summaries.append(summary)
|
||||||
|
return "\n\n".join(summaries)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
from langchain.tools import tool
|
||||||
|
|
||||||
|
class CalculatorTools():
|
||||||
|
|
||||||
|
@tool("Make a calculation")
|
||||||
|
def calculate(operation):
|
||||||
|
"""Useful to perform any mathematical calculations,
|
||||||
|
like sum, minus, multiplication, division, etc.
|
||||||
|
The input to this tool should be a mathematical
|
||||||
|
expression, a couple examples are `200*7` or `5000/2*10`
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return eval(operation)
|
||||||
|
except SyntaxError:
|
||||||
|
return "Error: Invalid syntax in mathematical expression"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from langchain.tools import tool
|
||||||
|
|
||||||
|
|
||||||
|
class SearchTools():
|
||||||
|
|
||||||
|
@tool("Search the internet")
|
||||||
|
def search_internet(query):
|
||||||
|
"""Useful to search the internet
|
||||||
|
about a a given topic and return relevant results"""
|
||||||
|
top_result_to_return = 4
|
||||||
|
url = "https://google.serper.dev/search"
|
||||||
|
payload = json.dumps({"q": query})
|
||||||
|
headers = {
|
||||||
|
'X-API-KEY': os.environ['SERPER_API_KEY'],
|
||||||
|
'content-type': 'application/json'
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=headers, data=payload)
|
||||||
|
# check if there is an organic key
|
||||||
|
if 'organic' not in response.json():
|
||||||
|
return "Sorry, I couldn't find anything about that, there could be an error with you serper api key."
|
||||||
|
else:
|
||||||
|
results = response.json()['organic']
|
||||||
|
string = []
|
||||||
|
for result in results[:top_result_to_return]:
|
||||||
|
try:
|
||||||
|
string.append('\n'.join([
|
||||||
|
f"Title: {result['title']}", f"Link: {result['link']}",
|
||||||
|
f"Snippet: {result['snippet']}", "\n-----------------"
|
||||||
|
]))
|
||||||
|
except KeyError:
|
||||||
|
next
|
||||||
|
|
||||||
|
return '\n'.join(string)
|
||||||
45
installer/client/cli/agents/trip_planner/trip_agents.py
Normal file
45
installer/client/cli/agents/trip_planner/trip_agents.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
from crewai import Agent
|
||||||
|
|
||||||
|
from .tools.browser_tools import BrowserTools
|
||||||
|
from .tools.calculator_tools import CalculatorTools
|
||||||
|
from .tools.search_tools import SearchTools
|
||||||
|
|
||||||
|
|
||||||
|
class TripAgents():
|
||||||
|
|
||||||
|
def city_selection_agent(self):
|
||||||
|
return Agent(
|
||||||
|
role='City Selection Expert',
|
||||||
|
goal='Select the best city based on weather, season, and prices',
|
||||||
|
backstory='An expert in analyzing travel data to pick ideal destinations',
|
||||||
|
tools=[
|
||||||
|
SearchTools.search_internet,
|
||||||
|
BrowserTools.scrape_and_summarize_website,
|
||||||
|
],
|
||||||
|
verbose=True)
|
||||||
|
|
||||||
|
def local_expert(self):
|
||||||
|
return Agent(
|
||||||
|
role='Local Expert at this city',
|
||||||
|
goal='Provide the BEST insights about the selected city',
|
||||||
|
backstory="""A knowledgeable local guide with extensive information
|
||||||
|
about the city, it's attractions and customs""",
|
||||||
|
tools=[
|
||||||
|
SearchTools.search_internet,
|
||||||
|
BrowserTools.scrape_and_summarize_website,
|
||||||
|
],
|
||||||
|
verbose=True)
|
||||||
|
|
||||||
|
def travel_concierge(self):
|
||||||
|
return Agent(
|
||||||
|
role='Amazing Travel Concierge',
|
||||||
|
goal="""Create the most amazing travel itineraries with budget and
|
||||||
|
packing suggestions for the city""",
|
||||||
|
backstory="""Specialist in travel planning and logistics with
|
||||||
|
decades of experience""",
|
||||||
|
tools=[
|
||||||
|
SearchTools.search_internet,
|
||||||
|
BrowserTools.scrape_and_summarize_website,
|
||||||
|
CalculatorTools.calculate,
|
||||||
|
],
|
||||||
|
verbose=True)
|
||||||
83
installer/client/cli/agents/trip_planner/trip_tasks.py
Normal file
83
installer/client/cli/agents/trip_planner/trip_tasks.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
from crewai import Task
|
||||||
|
from textwrap import dedent
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
|
||||||
|
class TripTasks():
|
||||||
|
|
||||||
|
def identify_task(self, agent, origin, cities, interests, range):
|
||||||
|
return Task(description=dedent(f"""
|
||||||
|
Analyze and select the best city for the trip based
|
||||||
|
on specific criteria such as weather patterns, seasonal
|
||||||
|
events, and travel costs. This task involves comparing
|
||||||
|
multiple cities, considering factors like current weather
|
||||||
|
conditions, upcoming cultural or seasonal events, and
|
||||||
|
overall travel expenses.
|
||||||
|
|
||||||
|
Your final answer must be a detailed
|
||||||
|
report on the chosen city, and everything you found out
|
||||||
|
about it, including the actual flight costs, weather
|
||||||
|
forecast and attractions.
|
||||||
|
{self.__tip_section()}
|
||||||
|
|
||||||
|
Traveling from: {origin}
|
||||||
|
City Options: {cities}
|
||||||
|
Trip Date: {range}
|
||||||
|
Traveler Interests: {interests}
|
||||||
|
"""),
|
||||||
|
agent=agent)
|
||||||
|
|
||||||
|
def gather_task(self, agent, origin, interests, range):
|
||||||
|
return Task(description=dedent(f"""
|
||||||
|
As a local expert on this city you must compile an
|
||||||
|
in-depth guide for someone traveling there and wanting
|
||||||
|
to have THE BEST trip ever!
|
||||||
|
Gather information about key attractions, local customs,
|
||||||
|
special events, and daily activity recommendations.
|
||||||
|
Find the best spots to go to, the kind of place only a
|
||||||
|
local would know.
|
||||||
|
This guide should provide a thorough overview of what
|
||||||
|
the city has to offer, including hidden gems, cultural
|
||||||
|
hotspots, must-visit landmarks, weather forecasts, and
|
||||||
|
high level costs.
|
||||||
|
|
||||||
|
The final answer must be a comprehensive city guide,
|
||||||
|
rich in cultural insights and practical tips,
|
||||||
|
tailored to enhance the travel experience.
|
||||||
|
{self.__tip_section()}
|
||||||
|
|
||||||
|
Trip Date: {range}
|
||||||
|
Traveling from: {origin}
|
||||||
|
Traveler Interests: {interests}
|
||||||
|
"""),
|
||||||
|
agent=agent)
|
||||||
|
|
||||||
|
def plan_task(self, agent, origin, interests, range):
|
||||||
|
return Task(description=dedent(f"""
|
||||||
|
Expand this guide into a a full 7-day travel
|
||||||
|
itinerary with detailed per-day plans, including
|
||||||
|
weather forecasts, places to eat, packing suggestions,
|
||||||
|
and a budget breakdown.
|
||||||
|
|
||||||
|
You MUST suggest actual places to visit, actual hotels
|
||||||
|
to stay and actual restaurants to go to.
|
||||||
|
|
||||||
|
This itinerary should cover all aspects of the trip,
|
||||||
|
from arrival to departure, integrating the city guide
|
||||||
|
information with practical travel logistics.
|
||||||
|
|
||||||
|
Your final answer MUST be a complete expanded travel plan,
|
||||||
|
formatted as markdown, encompassing a daily schedule,
|
||||||
|
anticipated weather conditions, recommended clothing and
|
||||||
|
items to pack, and a detailed budget, ensuring THE BEST
|
||||||
|
TRIP EVER, Be specific and give it a reason why you picked
|
||||||
|
# up each place, what make them special! {self.__tip_section()}
|
||||||
|
|
||||||
|
Trip Date: {range}
|
||||||
|
Traveling from: {origin}
|
||||||
|
Traveler Interests: {interests}
|
||||||
|
"""),
|
||||||
|
agent=agent)
|
||||||
|
|
||||||
|
def __tip_section(self):
|
||||||
|
return "If you do your BEST WORK, I'll tip you $100!"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from .utils import Standalone, Update, Setup, Alias
|
from .utils import Standalone, Update, Setup, Alias, AgentSetup
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
@@ -16,6 +16,12 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--copy", "-C", help="Copy the response to the clipboard", action="store_true"
|
"--copy", "-C", help="Copy the response to the clipboard", action="store_true"
|
||||||
)
|
)
|
||||||
|
subparsers = parser.add_subparsers(dest='command', help='Sub-command help')
|
||||||
|
agents_parser = subparsers.add_parser('agents', help='Crew command help')
|
||||||
|
agents_parser.add_argument(
|
||||||
|
"trip_planner", help="The origin city for the trip")
|
||||||
|
agents_parser.add_argument(
|
||||||
|
'ApiKeys', help="enter API keys for tools", action="store_true")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--output",
|
"--output",
|
||||||
"-o",
|
"-o",
|
||||||
@@ -67,6 +73,20 @@ def main():
|
|||||||
Update()
|
Update()
|
||||||
Alias()
|
Alias()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
if args.command == "agents":
|
||||||
|
from .agents.trip_planner.main import planner_cli
|
||||||
|
if args.ApiKeys:
|
||||||
|
AgentSetup().apiKeys()
|
||||||
|
sys.exit()
|
||||||
|
if not args.trip_planner:
|
||||||
|
print("Please provide an agent")
|
||||||
|
print(f"Available Agents:")
|
||||||
|
for agent in tripcrew.agents:
|
||||||
|
print(agent)
|
||||||
|
else:
|
||||||
|
tripcrew = planner_cli()
|
||||||
|
tripcrew.ask()
|
||||||
|
sys.exit()
|
||||||
if args.update:
|
if args.update:
|
||||||
Update()
|
Update()
|
||||||
Alias()
|
Alias()
|
||||||
|
|||||||
@@ -400,3 +400,32 @@ class Transcribe:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error:", e)
|
print("Error:", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class AgentSetup:
|
||||||
|
def apiKeys(self):
|
||||||
|
"""Method to set the API keys in the environment file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("Welcome to Fabric. Let's get started.")
|
||||||
|
browserless = input("Please enter your Browserless API key\n")
|
||||||
|
serper = input("Please enter your Serper API key\n")
|
||||||
|
|
||||||
|
# Entries to be added
|
||||||
|
browserless_entry = f"BROWSERLESS_API_KEY={browserless}"
|
||||||
|
serper_entry = f"SERPER_API_KEY={serper}"
|
||||||
|
|
||||||
|
# Check and write to the file
|
||||||
|
with open(env_file, "r+") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Determine if the file ends with a newline
|
||||||
|
if content.endswith('\n'):
|
||||||
|
# If it ends with a newline, we directly write the new entries
|
||||||
|
f.write(f"{browserless_entry}\n{serper_entry}\n")
|
||||||
|
else:
|
||||||
|
# If it does not end with a newline, add one before the new entries
|
||||||
|
f.write(f"\n{browserless_entry}\n{serper_entry}\n")
|
||||||
|
|||||||
1831
poetry.lock
generated
1831
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,11 @@ packages = [
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.10"
|
python = "^3.10"
|
||||||
|
crewai = "^0.11.0"
|
||||||
|
unstructured = "0.10.25"
|
||||||
|
pyowm = "3.3.0"
|
||||||
|
tools = "^0.1.9"
|
||||||
|
langchain-community = "^0.0.24"
|
||||||
|
|
||||||
[tool.poetry.group.cli.dependencies]
|
[tool.poetry.group.cli.dependencies]
|
||||||
pyyaml = "^6.0.1"
|
pyyaml = "^6.0.1"
|
||||||
@@ -33,7 +38,6 @@ gevent = "^23.9.1"
|
|||||||
httpx = "^0.26.0"
|
httpx = "^0.26.0"
|
||||||
tqdm = "^4.66.1"
|
tqdm = "^4.66.1"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.server.dependencies]
|
[tool.poetry.group.server.dependencies]
|
||||||
requests = "^2.31.0"
|
requests = "^2.31.0"
|
||||||
openai = "^1.12.0"
|
openai = "^1.12.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user