2023-03-17 15:55:15 +00:00
from env import settings
2023-03-21 12:49:47 +00:00
from typing import Dict
2023-03-17 15:55:15 +00:00
import requests
from llama_index . readers . database import DatabaseReader
from llama_index import GPTSimpleVectorIndex
2023-03-19 06:17:36 +00:00
from bs4 import BeautifulSoup
2023-03-21 12:49:47 +00:00
from langchain . agents . agent import AgentExecutor
2023-03-17 15:55:15 +00:00
2023-03-18 09:20:18 +00:00
import subprocess
2023-03-18 12:26:19 +00:00
from . base import tool , BaseToolSet
2023-03-18 09:20:18 +00:00
2023-03-18 12:26:19 +00:00
class Terminal ( BaseToolSet ) :
@tool (
2023-03-18 09:20:18 +00:00
name = " Terminal " ,
description = " Executes commands in a terminal. "
2023-03-21 04:41:10 +00:00
" You can install packages with pip, apt, etc. "
2023-03-18 09:20:18 +00:00
" Input should be valid commands, "
2023-03-20 08:27:20 +00:00
" and the output will be any output from running that command. " ,
2023-03-18 09:20:18 +00:00
)
2023-03-20 08:27:20 +00:00
def inference ( self , commands : str ) - > str :
2023-03-18 09:20:18 +00:00
""" Run commands and return final output. """
try :
output = subprocess . run (
commands ,
shell = True ,
stdout = subprocess . PIPE ,
stderr = subprocess . STDOUT ,
) . stdout . decode ( )
except Exception as e :
2023-03-20 08:27:20 +00:00
output = str ( e )
print (
f " \n Processed Terminal, Input Commands: { commands } "
f " Output Answer: { output } "
)
2023-03-18 09:20:18 +00:00
return output
2023-03-17 15:55:15 +00:00
2023-03-21 12:20:15 +00:00
class CodeEditor ( BaseToolSet ) :
@tool (
name = " CodeEditor.WRITE " ,
description = " Writes and appends code. "
" It can be used to write or append code in any language. "
" If the code is completed, use the Terminal tool to execute it, if not, append the code through the CodeEditor tool. "
" Input should be filename, status, code. Status will be ' complete ' or ' incomplete ' . ex. ' test.py|complete \n print( ' hello world ' ) \n "
" and the output will be status and last line. status will be ' complete ' or ' incomplete ' or ' error ' . " ,
)
def write ( self , inputs : str ) - > str :
""" Save codes to file and return success or failure. """
filename , status_and_code = inputs . split ( " | " , 1 )
status , code = status_and_code . split ( " \n " , 1 )
if status != " complete " and status != " incomplete " :
return " error: status must be complete or incomplete "
try :
with open ( filename , " a " ) as f :
f . write ( code )
output = status + " \n Last line was: " + code . split ( " \n " ) [ - 1 ]
except Exception as e :
output = " error "
print (
f " \n Processed CodeEditor, Input Codes: { code } " f " Output Answer: { output } "
)
return output
2023-03-18 12:26:19 +00:00
class RequestsGet ( BaseToolSet ) :
@tool (
2023-03-17 15:55:15 +00:00
name = " requests_get " ,
description = " A portal to the internet. "
" Use this when you need to get specific content from a website. "
" Input should be a url (i.e. https://www.google.com). "
" The output will be the text response of the GET request. " ,
)
def inference ( self , url : str ) - > str :
""" Run the tool. """
2023-03-19 06:17:36 +00:00
html = requests . get ( url ) . text
soup = BeautifulSoup ( html )
non_readable_tags = soup . find_all (
[ " script " , " style " , " header " , " footer " , " form " ]
)
2023-03-17 15:55:15 +00:00
2023-03-19 06:17:36 +00:00
for non_readable_tag in non_readable_tags :
non_readable_tag . extract ( )
content = soup . get_text ( " \n " , strip = True )
if len ( content ) > 300 :
content = content [ : 300 ] + " ... "
2023-03-20 08:27:20 +00:00
print (
f " \n Processed RequestsGet, Input Url: { url } " f " Output Contents: { content } "
)
2023-03-19 06:17:36 +00:00
return content
2023-03-17 15:55:15 +00:00
2023-03-18 12:26:19 +00:00
class WineDB ( BaseToolSet ) :
2023-03-17 15:55:15 +00:00
def __init__ ( self ) :
db = DatabaseReader (
scheme = " postgresql " , # Database Scheme
host = settings [ " WINEDB_HOST " ] , # Database Host
port = " 5432 " , # Database Port
user = " alphadom " , # Database User
password = settings [ " WINEDB_PASSWORD " ] , # Database Password
dbname = " postgres " , # Database Name
)
self . columns = [ " nameEn " , " nameKo " , " description " ]
concat_columns = str ( " , ' - ' , " . join ( [ f ' " { i } " ' for i in self . columns ] ) )
query = f """
SELECT
Concat ( { concat_columns } )
FROM wine
"""
documents = db . load_data ( query = query )
self . index = GPTSimpleVectorIndex ( documents )
2023-03-18 12:26:19 +00:00
@tool (
2023-03-21 12:20:15 +00:00
name = " Wine Recommendation " ,
2023-03-17 15:55:15 +00:00
description = " A tool to recommend wines based on a user ' s input. "
" Inputs are necessary factors for wine recommendations, such as the user ' s mood today, side dishes to eat with wine, people to drink wine with, what things you want to do, the scent and taste of their favorite wine. "
" The output will be a list of recommended wines. "
" The tool is based on a database of wine reviews, which is stored in a database. " ,
)
def inference ( self , query : str ) - > str :
""" Run the tool. """
results = self . index . query ( query )
wine = " \n " . join (
[
f " { i } : { j } "
for i , j in zip (
self . columns , results . source_nodes [ 0 ] . source_text . split ( " - " )
)
]
)
2023-03-20 08:27:20 +00:00
output = results . response + " \n \n " + wine
print ( f " \n Processed WineDB, Input Query: { query } " f " Output Wine: { wine } " )
return output
2023-03-17 15:55:15 +00:00
2023-03-18 12:26:19 +00:00
class ExitConversation ( BaseToolSet ) :
2023-03-21 12:49:47 +00:00
def __init__ ( self , executors : Dict [ str , AgentExecutor ] ) :
self . executors = executors
2023-03-21 12:20:15 +00:00
2023-03-18 12:26:19 +00:00
@tool (
2023-03-21 12:49:47 +00:00
name = " Exit Conversation " ,
2023-03-17 15:55:15 +00:00
description = " A tool to exit the conversation. "
2023-03-21 12:49:47 +00:00
" Use this when you want to exit the conversation. "
2023-03-21 12:20:15 +00:00
" Input should be a user ' s key. "
2023-03-17 15:55:15 +00:00
" The output will be a message that the conversation is over. " ,
)
2023-03-21 12:20:15 +00:00
def exit ( self , key : str ) - > str :
2023-03-17 15:55:15 +00:00
""" Run the tool. """
2023-03-21 12:49:47 +00:00
self . executors . pop ( key )
2023-03-18 09:20:18 +00:00
2023-03-21 12:20:15 +00:00
print ( f " \n Processed ExitConversation. " )
2023-03-20 08:27:20 +00:00
2023-03-21 12:49:47 +00:00
return f " Exit conversation. "