2023-03-28 22:25:42 +00:00
import browse
import json
2023-04-07 23:30:04 +00:00
from memory import get_memory
2023-03-29 01:40:46 +00:00
import datetime
2023-03-30 09:04:09 +00:00
import agent_manager as agents
2023-03-31 03:15:14 +00:00
import speak
from config import Config
2023-04-01 09:35:32 +00:00
import ai_functions as ai
2023-04-05 01:32:15 +00:00
from file_operations import read_file , write_to_file , append_to_file , delete_file , search_files
2023-04-13 04:04:26 +00:00
from execute_code import execute_python_file , execute_shell
2023-04-02 23:50:51 +00:00
from json_parser import fix_and_parse_json
2023-04-07 15:02:48 +00:00
from image_gen import generate_image
2023-04-03 19:11:15 +00:00
from duckduckgo_search import ddg
2023-04-03 20:44:10 +00:00
from googleapiclient . discovery import build
from googleapiclient . errors import HttpError
2023-03-31 03:15:14 +00:00
cfg = Config ( )
2023-03-30 09:04:09 +00:00
2023-03-28 22:25:42 +00:00
2023-04-04 20:53:59 +00:00
def is_valid_int ( value ) :
try :
int ( value )
return True
except ValueError :
return False
2023-04-12 21:05:14 +00:00
2023-03-29 01:40:46 +00:00
def get_command ( response ) :
2023-04-02 17:03:37 +00:00
""" Parse the response and return the command name and arguments """
2023-03-29 01:40:46 +00:00
try :
2023-04-02 23:50:51 +00:00
response_json = fix_and_parse_json ( response )
2023-04-09 12:58:05 +00:00
2023-04-03 10:30:06 +00:00
if " command " not in response_json :
return " Error: " , " Missing ' command ' object in JSON "
2023-04-09 12:58:05 +00:00
2023-03-29 01:40:46 +00:00
command = response_json [ " command " ]
2023-04-03 10:30:06 +00:00
if " name " not in command :
return " Error: " , " Missing ' name ' field in ' command ' object "
2023-04-09 12:58:05 +00:00
2023-03-29 01:40:46 +00:00
command_name = command [ " name " ]
2023-04-03 10:30:06 +00:00
# Use an empty dictionary if 'args' field is not present in 'command' object
arguments = command . get ( " args " , { } )
2023-03-29 01:40:46 +00:00
return command_name , arguments
except json . decoder . JSONDecodeError :
2023-03-30 11:46:36 +00:00
return " Error: " , " Invalid JSON "
2023-03-29 01:40:46 +00:00
# All other errors, return "Error: + error message"
except Exception as e :
2023-03-30 11:46:36 +00:00
return " Error: " , str ( e )
2023-03-29 01:40:46 +00:00
2023-04-02 08:13:15 +00:00
2023-03-29 01:40:46 +00:00
def execute_command ( command_name , arguments ) :
2023-04-09 13:42:53 +00:00
""" Execute the command and return the result """
2023-04-07 23:30:04 +00:00
memory = get_memory ( cfg )
2023-04-07 23:13:18 +00:00
2023-03-29 01:40:46 +00:00
try :
if command_name == " google " :
2023-04-07 23:13:18 +00:00
2023-04-03 20:44:10 +00:00
# Check if the Google API key is set and use the official search method
# If the API key is not set or has only whitespaces, use the unofficial search method
if cfg . google_api_key and ( cfg . google_api_key . strip ( ) if cfg . google_api_key else None ) :
return google_official_search ( arguments [ " input " ] )
else :
return google_search ( arguments [ " input " ] )
2023-03-29 01:40:46 +00:00
elif command_name == " memory_add " :
2023-04-04 00:31:01 +00:00
return memory . add ( arguments [ " string " ] )
2023-03-30 09:04:09 +00:00
elif command_name == " start_agent " :
2023-04-02 08:13:15 +00:00
return start_agent (
arguments [ " name " ] ,
arguments [ " task " ] ,
arguments [ " prompt " ] )
2023-03-30 09:04:09 +00:00
elif command_name == " message_agent " :
return message_agent ( arguments [ " key " ] , arguments [ " message " ] )
elif command_name == " list_agents " :
return list_agents ( )
elif command_name == " delete_agent " :
return delete_agent ( arguments [ " key " ] )
2023-03-30 09:06:31 +00:00
elif command_name == " get_text_summary " :
2023-04-04 01:20:42 +00:00
return get_text_summary ( arguments [ " url " ] , arguments [ " question " ] )
2023-03-30 09:10:52 +00:00
elif command_name == " get_hyperlinks " :
return get_hyperlinks ( arguments [ " url " ] )
2023-04-01 03:08:30 +00:00
elif command_name == " read_file " :
return read_file ( arguments [ " file " ] )
2023-03-30 09:08:13 +00:00
elif command_name == " write_to_file " :
2023-03-30 11:47:55 +00:00
return write_to_file ( arguments [ " file " ] , arguments [ " text " ] )
2023-04-01 03:08:30 +00:00
elif command_name == " append_to_file " :
return append_to_file ( arguments [ " file " ] , arguments [ " text " ] )
elif command_name == " delete_file " :
return delete_file ( arguments [ " file " ] )
2023-04-05 01:32:15 +00:00
elif command_name == " search_files " :
return search_files ( arguments [ " directory " ] )
2023-03-30 11:47:55 +00:00
elif command_name == " browse_website " :
2023-04-04 01:20:42 +00:00
return browse_website ( arguments [ " url " ] , arguments [ " question " ] )
2023-04-02 08:13:15 +00:00
# TODO: Change these to take in a file rather than pasted code, if
# non-file is given, return instructions "Input should be a python
# filepath, write your code to file and try again"
2023-04-01 09:35:32 +00:00
elif command_name == " evaluate_code " :
return ai . evaluate_code ( arguments [ " code " ] )
elif command_name == " improve_code " :
return ai . improve_code ( arguments [ " suggestions " ] , arguments [ " code " ] )
elif command_name == " write_tests " :
return ai . write_tests ( arguments [ " code " ] , arguments . get ( " focus " ) )
2023-04-01 15:01:36 +00:00
elif command_name == " execute_python_file " : # Add this command
return execute_python_file ( arguments [ " file " ] )
2023-04-13 04:04:26 +00:00
elif command_name == " execute_shell " :
2023-04-10 04:01:48 +00:00
if cfg . execute_local_commands :
2023-04-13 04:04:26 +00:00
return execute_shell ( arguments [ " command_line " ] )
2023-04-10 04:01:48 +00:00
else :
2023-04-12 16:32:17 +00:00
return " You are not allowed to run local shell commands. To execute shell commands, EXECUTE_LOCAL_COMMANDS must be set to ' True ' in your config. Do not attempt to bypass the restriction. "
2023-04-08 11:27:05 +00:00
elif command_name == " generate_image " :
2023-04-07 15:02:48 +00:00
return generate_image ( arguments [ " prompt " ] )
2023-04-09 08:28:36 +00:00
elif command_name == " do_nothing " :
return " No action performed. "
2023-03-30 09:10:05 +00:00
elif command_name == " task_complete " :
shutdown ( )
2023-03-29 01:40:46 +00:00
else :
2023-04-12 02:10:37 +00:00
return f " Unknown command ' { command_name } ' . Please refer to the ' COMMANDS ' list for available commands and only respond in the specified JSON format. "
2023-04-01 15:01:36 +00:00
# All errors, return "Error: + error message"
2023-03-29 01:40:46 +00:00
except Exception as e :
return " Error: " + str ( e )
2023-03-28 22:25:42 +00:00
2023-04-02 08:13:15 +00:00
2023-03-29 01:40:46 +00:00
def get_datetime ( ) :
2023-04-02 17:03:37 +00:00
""" Return the current date and time """
2023-04-02 08:13:15 +00:00
return " Current date and time: " + \
datetime . datetime . now ( ) . strftime ( " % Y- % m- %d % H: % M: % S " )
2023-03-29 01:40:46 +00:00
2023-03-31 03:15:14 +00:00
def google_search ( query , num_results = 8 ) :
2023-04-02 17:03:37 +00:00
""" Return the results of a google search """
2023-03-28 22:25:42 +00:00
search_results = [ ]
2023-04-03 19:11:15 +00:00
for j in ddg ( query , max_results = num_results ) :
2023-03-28 22:25:42 +00:00
search_results . append ( j )
2023-03-31 03:15:14 +00:00
2023-03-28 22:25:42 +00:00
return json . dumps ( search_results , ensure_ascii = False , indent = 4 )
2023-04-12 21:05:14 +00:00
2023-04-03 20:44:10 +00:00
def google_official_search ( query , num_results = 8 ) :
2023-04-04 09:28:15 +00:00
""" Return the results of a google search using the official Google API """
2023-04-03 20:44:10 +00:00
from googleapiclient . discovery import build
from googleapiclient . errors import HttpError
import json
try :
# Get the Google API key and Custom Search Engine ID from the config file
api_key = cfg . google_api_key
custom_search_engine_id = cfg . custom_search_engine_id
# Initialize the Custom Search API service
service = build ( " customsearch " , " v1 " , developerKey = api_key )
2023-04-09 12:58:05 +00:00
2023-04-03 20:44:10 +00:00
# Send the search query and retrieve the results
result = service . cse ( ) . list ( q = query , cx = custom_search_engine_id , num = num_results ) . execute ( )
# Extract the search result items from the response
search_results = result . get ( " items " , [ ] )
2023-04-09 12:58:05 +00:00
2023-04-03 20:44:10 +00:00
# Create a list of only the URLs from the search results
search_results_links = [ item [ " link " ] for item in search_results ]
except HttpError as e :
# Handle errors in the API call
error_details = json . loads ( e . content . decode ( ) )
2023-04-09 12:58:05 +00:00
2023-04-03 20:44:10 +00:00
# Check if the error is related to an invalid or missing API key
if error_details . get ( " error " , { } ) . get ( " code " ) == 403 and " invalid API key " in error_details . get ( " error " , { } ) . get ( " message " , " " ) :
return " Error: The provided Google API key is invalid or missing. "
else :
return f " Error: { e } "
# Return the list of search result URLs
return search_results_links
2023-04-02 08:13:15 +00:00
2023-04-12 21:05:14 +00:00
2023-04-04 01:20:42 +00:00
def browse_website ( url , question ) :
2023-04-04 09:47:37 +00:00
""" Browse a website and return the summary and links """
2023-04-04 01:20:42 +00:00
summary = get_text_summary ( url , question )
2023-03-30 09:23:52 +00:00
links = get_hyperlinks ( url )
2023-03-30 11:45:15 +00:00
# Limit links to 5
if len ( links ) > 5 :
links = links [ : 5 ]
2023-03-30 09:23:52 +00:00
result = f """ Website Content Summary: { summary } \n \n Links: { links } """
return result
2023-04-02 08:13:15 +00:00
2023-04-04 01:20:42 +00:00
def get_text_summary ( url , question ) :
2023-04-02 17:03:37 +00:00
""" Return the results of a google search """
2023-03-29 08:43:32 +00:00
text = browse . scrape_text ( url )
2023-04-04 01:20:42 +00:00
summary = browse . summarize_text ( text , question )
2023-03-28 22:25:42 +00:00
return """ " Result " : """ + summary
2023-04-02 08:13:15 +00:00
2023-03-30 09:10:52 +00:00
def get_hyperlinks ( url ) :
2023-04-02 17:03:37 +00:00
""" Return the results of a google search """
2023-03-30 11:45:15 +00:00
link_list = browse . scrape_links ( url )
return link_list
2023-03-30 09:10:52 +00:00
2023-04-02 08:13:15 +00:00
2023-03-28 22:25:42 +00:00
def commit_memory ( string ) :
2023-04-02 17:03:37 +00:00
""" Commit a string to memory """
2023-03-30 09:15:35 +00:00
_text = f """ Committing memory with string " { string } " """
2023-03-28 22:25:42 +00:00
mem . permanent_memory . append ( string )
return _text
2023-04-02 08:13:15 +00:00
2023-03-28 22:25:42 +00:00
def delete_memory ( key ) :
2023-04-02 17:03:37 +00:00
""" Delete a memory with a given key """
2023-03-28 22:25:42 +00:00
if key > = 0 and key < len ( mem . permanent_memory ) :
_text = " Deleting memory with key " + str ( key )
del mem . permanent_memory [ key ]
print ( _text )
return _text
else :
print ( " Invalid key, cannot delete memory. " )
return None
2023-04-02 08:13:15 +00:00
2023-03-28 22:25:42 +00:00
def overwrite_memory ( key , string ) :
2023-04-03 11:51:36 +00:00
""" Overwrite a memory with a given key and string """
2023-04-04 20:53:59 +00:00
# Check if the key is a valid integer
if is_valid_int ( key ) :
key_int = int ( key )
# Check if the integer key is within the range of the permanent_memory list
if 0 < = key_int < len ( mem . permanent_memory ) :
_text = " Overwriting memory with key " + str ( key ) + " and string " + string
# Overwrite the memory slot with the given integer key and string
mem . permanent_memory [ key_int ] = string
print ( _text )
return _text
else :
print ( f " Invalid key ' { key } ' , out of range. " )
return None
# Check if the key is a valid string
elif isinstance ( key , str ) :
_text = " Overwriting memory with key " + key + " and string " + string
# Overwrite the memory slot with the given string key and string
2023-04-06 07:07:54 +00:00
mem . permanent_memory [ key ] = string
2023-03-28 22:25:42 +00:00
print ( _text )
return _text
else :
2023-04-04 20:53:59 +00:00
print ( f " Invalid key ' { key } ' , must be an integer or a string. " )
2023-03-28 22:25:42 +00:00
return None
2023-03-30 09:08:13 +00:00
2023-04-02 08:13:15 +00:00
2023-03-30 09:08:13 +00:00
def shutdown ( ) :
2023-04-02 17:03:37 +00:00
""" Shut down the program """
2023-03-30 09:08:13 +00:00
print ( " Shutting down... " )
quit ( )
2023-04-02 08:13:15 +00:00
2023-04-03 02:38:21 +00:00
def start_agent ( name , task , prompt , model = cfg . fast_llm_model ) :
2023-04-02 17:03:37 +00:00
""" Start an agent with a given name, task, and prompt """
2023-03-31 03:15:14 +00:00
global cfg
# Remove underscores from name
voice_name = name . replace ( " _ " , " " )
first_message = f """ You are { name } . Respond with: " Acknowledged " . """
agent_intro = f " { voice_name } here, Reporting for duty! "
2023-03-30 09:08:13 +00:00
2023-03-31 03:15:14 +00:00
# Create agent
if cfg . speak_mode :
2023-03-31 21:49:17 +00:00
speak . say_text ( agent_intro , 1 )
2023-03-31 03:15:14 +00:00
key , ack = agents . create_agent ( task , first_message , model )
2023-03-28 22:25:42 +00:00
2023-03-31 03:15:14 +00:00
if cfg . speak_mode :
speak . say_text ( f " Hello { voice_name } . Your task is as follows. { task } . " )
2023-03-28 22:25:42 +00:00
2023-03-31 03:15:14 +00:00
# Assign task (prompt), get response
agent_response = message_agent ( key , prompt )
return f " Agent { name } created with key { key } . First response: { agent_response } "
2023-03-30 09:04:09 +00:00
2023-04-02 08:13:15 +00:00
2023-03-30 09:04:09 +00:00
def message_agent ( key , message ) :
2023-04-02 17:03:37 +00:00
""" Message an agent with a given key and message """
2023-03-31 03:15:14 +00:00
global cfg
2023-04-05 01:53:41 +00:00
2023-04-04 20:53:59 +00:00
# Check if the key is a valid integer
2023-04-05 01:53:41 +00:00
if is_valid_int ( key ) :
agent_response = agents . message_agent ( int ( key ) , message )
# Check if the key is a valid string
elif isinstance ( key , str ) :
agent_response = agents . message_agent ( key , message )
else :
return " Invalid key, must be an integer or a string. "
2023-03-31 03:15:14 +00:00
# Speak response
if cfg . speak_mode :
2023-03-31 21:49:17 +00:00
speak . say_text ( agent_response , 1 )
2023-04-05 01:53:41 +00:00
return agent_response
2023-03-30 09:04:09 +00:00
2023-04-02 08:13:15 +00:00
2023-03-30 09:04:09 +00:00
def list_agents ( ) :
2023-04-02 17:03:37 +00:00
""" List all agents """
2023-03-30 09:04:09 +00:00
return agents . list_agents ( )
2023-04-02 08:13:15 +00:00
2023-03-30 09:04:09 +00:00
def delete_agent ( key ) :
2023-04-02 17:03:37 +00:00
""" Delete an agent with a given key """
2023-03-30 09:04:09 +00:00
result = agents . delete_agent ( key )
2023-04-02 08:13:15 +00:00
if not result :
2023-03-30 09:04:09 +00:00
return f " Agent { key } does not exist. "
2023-04-09 08:28:36 +00:00
return f " Agent { key } deleted. "