Skip to content

Commit

Permalink
Agent and Tools with External API calls
Browse files Browse the repository at this point in the history
  • Loading branch information
r-manimaran committed Jun 30, 2024
1 parent 268544b commit 3f89aec
Show file tree
Hide file tree
Showing 8 changed files with 410 additions and 2 deletions.
4 changes: 2 additions & 2 deletions MultiDataSource-Agents-Tools/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@
# print(f'6. Response: {response["output"]}')

#Below uses Arxiv and search in research paper
#response = agent_executor.invoke({"input": "What is the paper 1605.08386 talks about?"}, include_run_info=True)
#print(f'6. Response: {response["output"]}')
response = agent_executor.invoke({"input": "What is the paper 1605.08386 talks about?"}, include_run_info=True)
print(f'6. Response: {response["output"]}')

# use streamlit app to get output and print response
import streamlit as st
Expand Down
1 change: 1 addition & 0 deletions agent-tool-externalApi/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
163 changes: 163 additions & 0 deletions agent-tool-externalApi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
venv-app/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
Binary file added agent-tool-externalApi/image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added agent-tool-externalApi/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
215 changes: 215 additions & 0 deletions agent-tool-externalApi/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
#Import Agents and Tools
from langchain.agents import initialize_agent, Tool, AgentType
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain_community.utilities import TextRequestsWrapper
from langchain_openai import OpenAI

#import OpenAI API key and other required imports
import os
from dotenv import load_dotenv
from langchain.tools import BaseTool
import requests

load_dotenv()

#setup the LLM
llm = OpenAI(temperature=0.0)

# Tools to be added

def get_police_forces():
# Fetch police force data from an API
url = "https://data.police.uk/api/forces"
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
return None

def search_police_forces(name):
# Search for a specific police force by name
forces = get_police_forces()
matching_forces = []
if forces:
for force in forces:
if name.lower() in force["name"].lower():
matching_forces.append(force)

return matching_forces

return None

class search_police_force(BaseTool):
name = "search_police_force"
description = "Useful for when you need to search for a specific police force by name"

def _run(self, query:str) -> str:
# Use the search_police_force function to search for a police force
forces = search_police_forces(query)
return forces

async def _arun(self, query:str) -> str:
# Use the search_police_force function to search for a police force
raise NotImplementedError("tool does not support async")
'''
#example usuage
force_id = "devon"
police_force_data = search_police_forces(force_id)
print(police_force_data)
'''


def get_police_force_id(force_id):
url=f'https://data.police.uk/api/forces/{force_id}'
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
return None

class get_police_force_details(BaseTool):
name = "get_police_force_details"
description = "Useful for when you need to get details of a specific police force by ID"

def _run(self, query:str) -> str:
# Use the get_police_force_details function to get details of a police force
force_details = get_police_force_id(query)
return force_details

async def _arun(self, query:str) -> str:
# Use the get_police_force_details function to get details of a police force
raise NotImplementedError("tool does not support async")

'''
#example usuage
force_id = "devon-and-cornwall"
police_force_data = get_police_force_id(force_id)
print(police_force_data)
'''

def get_police_force_people(force_id):
url=f'https://data.police.uk/api/forces/{force_id}/people'
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
return None

class get_police_force_peoples(BaseTool):
name = "get_police_force_people"
description = "Useful for when you need to get people details of a specific police force by ID"

def _run(self, query:str) -> str:
# Use the get_police_force_people function to get details of people in a police force
force_people = get_police_force_people(query)
return force_people

async def _arun(self, query:str) -> str:
# Use the get_police_force_people function to get details of people in a police force
raise NotImplementedError("tool does not support async")
'''
# example usage
force_id = "devon-and-cornwall"
police_force_data = get_police_force_people(force_id)
print(police_force_data)
'''

def get_neighbourhoods(force_id):
url =f'https://data.police.uk/api/{force_id}/neighbourhoods'
cleaned_url = url.replace("'", "")
response = requests.get(cleaned_url)
neighbourhoods = response.json()

if response.status_code == 200:
names = [neighbourhood['name'] for neighbourhood in neighbourhoods]
names_string = ', '.join(names)
return names_string
else:
return None

class get_police_neighbourhoods(BaseTool):
name = "get_police_neighbourhoods"
description = "Useful for when you need to get a list of neighbourhoods in a specific police force by ID"

def _run(self, query:str) -> str:
# Use the get_neighbourhoods function to get a list of neighbourhoods in a police force
neighbourhoods = get_neighbourhoods(query)
return neighbourhoods

async def _arun(self, query:str) -> str:
# Use the get_neighbourhoods function to get a list of neighbourhoods in a police force
raise NotImplementedError("tool does not support async")

'''
#usage
force_id = "\'devon-and-cornwall\'"
neighbourhoods = get_neighbourhoods(force_id)
print(neighbourhoods)
'''

def locate_neighbourhood(latlong):
url=f'https://data.police.uk/api/locate-neighbourhood?q={latlong}'
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
return None

class locate_police_neighbourhood(BaseTool):
name = "locate_police_neighbourhood"
description = "Useful for when you need to locate a specific police force neighbourhood by latitude and longitude"

def _run(self, query:str) -> str:
# Use the locate_neighbourhood function to locate a neighbourhood in a police force
neighbourhood = locate_neighbourhood(query)
return neighbourhood

async def _arun(self, query:str) -> str:
# Use the locate_neighbourhood function to locate a neighbourhood in a police force
raise NotImplementedError("tool does not support async")
'''
# example usage
latlong = "51.509865,-0.118092"
neighbourhood_data = locate_neighbourhood(latlong)
print(neighbourhood_data)
'''

#Load the tools config that are needed

tools =[
Tool(
name="search_police_force",
func=search_police_force().run,
description="Useful for when you need to search for a specific police force by name"
),
Tool(
name="get_police_force_details",
func=get_police_force_details().run,
description="Useful for when you need to get details of a specific police force by ID"
),
Tool(
name="get_police_force_people",
func=get_police_force_peoples().run,
description="Useful for when you need to get people details of a specific police force by ID"
),
Tool(
name="get_police_neighbourhoods",
func=get_police_neighbourhoods().run,
description="Useful for when you need to get a list of neighbourhoods in a specific police force by ID"
),
Tool(
name="locate_police_neighbourhood",
func=locate_police_neighbourhood().run,
description="Useful for when you need to locate a specific police force neighbourhood by latitude and longitude"
),
]

tools = [search_police_force(),get_police_force_details(),get_police_neighbourhoods(), locate_police_neighbourhood()]
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
response = agent.run("Get the contact number for latitude 50.365, longitude -4.1423 police station")
print(response)
Loading

0 comments on commit 3f89aec

Please sign in to comment.