Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto refactoring - performed by GPT-4 #81

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions src/ai/system_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@
from tzlocal import get_localzone


def get_system_information(location: str):

def get_system_information(location: str) -> str:
"""
Get the system information including the current date/time, time zone, and location.

# Get the local time zone in IANA format
:param location: The location of the user as a string.
:return: A formatted string containing the date/time, time zone, and location.
"""
# Get the local time zone in IANA format
local_timezone = get_localzone()
return f"User's Current Date/Time: {datetime.now().strftime('%m/%d/%Y %H:%M:%S')}.\nUser's Current Time Zone: {local_timezone}.\nUser's Current Location: {location}"
current_datetime = datetime.now().strftime('%m/%d/%Y %H:%M:%S')

# Format the system information string
system_info = (
f"User's Current Date/Time: {current_datetime}.
"
f"User's Current Time Zone: {local_timezone}.
"
f"User's Current Location: {location}"
)
return system_info
27 changes: 24 additions & 3 deletions src/utilities/configuration_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,29 @@


def get_tool_configuration(configuration: dict, func_name: str) -> dict:
"""
Retrieve the tool-specific configuration.

Parameters:
configuration (dict): The main configuration dictionary containing all tool configurations.
func_name (str): The name of the function for which to retrieve the configuration.

Returns:
dict: The configuration dictionary for the specified function or the default configuration if not found.
"""
if func_name in configuration["tool_configurations"]:
return configuration["tool_configurations"][func_name]

return configuration["tool_configurations"]["default"]


def get_app_config_path():
def get_app_config_path() -> str:
"""
Get the file system path to the application configuration file.

Returns:
str: The path to the application configuration file, either from the environment variable or the default path.
"""
app_config_path = os.environ.get(
"APP_CONFIG_PATH",
"configurations/app_configs/config.json",
Expand All @@ -18,8 +34,13 @@ def get_app_config_path():
return app_config_path


def get_app_configuration():
"""Loads the configuration from the path"""
def get_app_configuration() -> dict:
"""
Load the application configuration from the configuration file.

Returns:
dict: The application configuration loaded from the file.
"""
app_config_path = get_app_config_path()

return ApplicationConfigurationLoader.from_file(app_config_path)
100 changes: 48 additions & 52 deletions src/utilities/parsing_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,70 +3,66 @@
import os
import logging

from langchain.schema.language_model import BaseLanguageModel
from src.utilities.json_repair import JsonRepair

logging.basicConfig(level=os.getenv("LOGGING_LEVEL", "INFO"))
# Configure logging
logging.basicConfig(level=logging.getLevelName(os.getenv('LOGGING_LEVEL', 'INFO')))
logger = logging.getLogger(__name__)

def parse_json(text: str, llm: BaseLanguageModel) -> dict:

# So....
text = text.strip()

# Hey look, another random thing to handle
text = text.replace("``` json", "```json")

# Handle JSON code blocks (whole response)
if text.startswith("```json") and text.endswith("```"):
text = text[7:-3]
# Constants
JSON_CODE_BLOCK_START = '```json'
JSON_CODE_BLOCK_END = '```'


def extract_json_block(text):
"""
Extract JSON from code blocks.

# Fucking...
text = text.strip()
:param text: String containing the text with potential JSON code blocks.
:return: The extracted JSON string if found, otherwise None.
"""
pattern = re.compile(r'```(?:json)?\n(.*?)```', re.DOTALL)
try:
match = pattern.search(text)
return match.group(1).strip() if match else None
except re.error as e:
logger.error(f'Regex error occurred: {e}')
return None

# Sometimes there are two lines of ``` code block nonsense
if text.startswith("```"):
text = text[3:]

if text.endswith("```"):
text = text[:-3]
def parse_json(text: str) -> dict:
"""
Parse a JSON string, repairing it if necessary.

# Annoying...
:param text: String containing the JSON to parse.
:return: A dictionary representation of the JSON.
"""
text = text.strip()

# Handle JSON code blocks (inside other text within a response)
pattern = re.compile(r"```(?:json)?\n(.*?)```", re.DOTALL)
# Check if the entire text is a JSON code block
if text.startswith(JSON_CODE_BLOCK_START) and text.endswith(JSON_CODE_BLOCK_END):
text = text[len(JSON_CODE_BLOCK_START):-len(JSON_CODE_BLOCK_END)].strip()

# Extract JSON from within the text
json_block = extract_json_block(text)
if json_block is not None:
text = json_block

# Attempt to parse the JSON
try:
action_match = pattern.search(text)
if action_match is not None:
logger.info("Handling JSON found inside of a code block...")
# Handles the json inside of the code block
text = action_match.group(1).strip()
response = json.loads(text, strict=False)
return response
elif (text.strip().startswith("{") and text.strip().endswith("}")) or (text.strip().startswith("[") and text.strip().endswith("]")):
logger.info("Handling JSON that is not inside of a code block...")
# Handles JSON responses that are not in code blocks
return json.loads(text.strip(), strict=False)
else:
# Just return this as the answer??
logger.warning("Gave up on handling JSON, returning text as final_answer...")
return {"final_answer": text}
except Exception as e:
return json.loads(text, strict=False)
except json.JSONDecodeError as e:
logger.warning('Failed to parse JSON, trying to repair it...')
try:
logger.warning("Failed to parse JSON, trying to repair it...")
# Try to repair the JSON
text = JsonRepair(text).repair()
return parse_json(text, None)
except Exception as e:
# Last-ditch effort, try to use the LLM to fix the JSON
logger.warning("Failed to repair JSON, trying to use LLM to fix it...")
if llm:
llm_fixed_json = llm.predict(
f"The following is badly formatted JSON, please fix it (only fix the JSON, do not otherwise modify the content):\n{text}\n\nAI: Sure, here is the fixed JSON (without modifying the content):\n"
)
return parse_json(llm_fixed_json, None)
else:
logger.error("Failed to parse JSON, and no LLM was provided to try to fix it.")
raise Exception(f"Could not parse LLM output: {text}") from e
repaired_text = JsonRepair(text).repair()
return json.loads(repaired_text, strict=False)
except json.JSONDecodeError as e:
error_msg = f'Failed to repair JSON. Original text: {text}, Error: {e}'
logger.error(error_msg)
raise ValueError(error_msg) from e

# Fallback if the text is not JSON
logger.warning('Gave up on handling JSON, returning text as final_answer...')
return {'final_answer': text}