added agents

This commit is contained in:
Jonathan Dunn 2024-02-28 10:17:57 -05:00
parent 1c71ac790d
commit a6aeb8ffed
14 changed files with 2275 additions and 3 deletions

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.10

View File

@ -0,0 +1 @@
3.10

View 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)

View 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)

View File

@ -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)

View File

@ -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"

View File

@ -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)

View 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)

View 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!"

View File

@ -1,4 +1,4 @@
from .utils import Standalone, Update, Setup, Alias
from .utils import Standalone, Update, Setup, Alias, AgentSetup
import argparse
import sys
import time
@ -16,6 +16,12 @@ def main():
parser.add_argument(
"--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(
"--output",
"-o",
@ -67,6 +73,20 @@ def main():
Update()
Alias()
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:
Update()
Alias()

View File

@ -400,3 +400,32 @@ class Transcribe:
except Exception as e:
print("Error:", e)
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

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,11 @@ packages = [
[tool.poetry.dependencies]
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]
pyyaml = "^6.0.1"
@ -33,7 +38,6 @@ gevent = "^23.9.1"
httpx = "^0.26.0"
tqdm = "^4.66.1"
[tool.poetry.group.server.dependencies]
requests = "^2.31.0"
openai = "^1.12.0"