Source code for danoan.llm_assistant.common.config

"""
LLM-assistant configuration API.
"""
from danoan.llm_assistant.common import exception, model
from danoan.llm_assistant.common.logging_config import setup_logging

import logging
import os
from functools import lru_cache
from pathlib import Path
import toml
from typing import Optional

setup_logging()
logger = logging.getLogger(__name__)

########################################
# Configuration files
########################################

LLM_ASSISTANT_ENV_VARIABLE = "LLM_ASSISTANT_CONFIGURATION_FOLDER"
LLM_ASSISTANT_CONFIGURATION_FILENAME = "llm-assistant-config.toml"


@lru_cache
def _get_first_configuration_filepath_within_file_hierarchy(
    base_dir: Path,
) -> Optional[Path]:
    """
    Traverses the parents of the working directory until
    the configuration file is found.
    """
    visited = set()
    folders_to_visit = [base_dir]
    while len(folders_to_visit) > 0:
        cur_folder = folders_to_visit.pop()
        if cur_folder in visited:
            break
        logger.debug(f"Visiting {cur_folder}")
        visited.add(cur_folder)
        folders_to_visit.append(cur_folder.parent)
        for p in cur_folder.iterdir():
            if not p.is_dir():
                if p.name == LLM_ASSISTANT_CONFIGURATION_FILENAME:
                    return p
                continue
    return None


[docs] def get_configuration_folder() -> Path: """ Return directory where configuration file is stored. First checks if a configuration file exists in the file hierarchy. If that is the case, return the directory where the configuration file is located. If the procedure above does not find a configuration file, return the value stored in the environment variable LLM_ASSISTANT_ENV_VARIABLE. If the environment variable is not defined, raise an error. Raises: EnvironmentVariableNotDefinedError: If the LLM_ASSISTANT_ENV_VARIABLE is not defined and a configuration file is not found in the file hierarchy """ logger.debug("Start hierarchical search of configuation file") config_filepath = _get_first_configuration_filepath_within_file_hierarchy( Path(os.getcwd()) ) if config_filepath: return config_filepath.parent logger.debug( "Hierarchical search failed. Check environment variable {LLM_ASSISTANT_ENV_VARIABLE}" ) if LLM_ASSISTANT_ENV_VARIABLE in os.environ: return Path(os.environ[LLM_ASSISTANT_ENV_VARIABLE]).expanduser() raise exception.EnvironmentVariableNotDefinedError()
[docs] def get_environment_variable_value() -> Path: f""" Return the value stored by {LLM_ASSISTANT_ENV_VARIABLE}. Raises: EnvironmentVariableNotDefinedError: If the LLM_ASSISTANT_ENV_VARIABLE is not defined and a configuration file is not found in the file hierarchy """ if LLM_ASSISTANT_ENV_VARIABLE in os.environ: return Path(os.environ[LLM_ASSISTANT_ENV_VARIABLE]).expanduser() raise exception.EnvironmentVariableNotDefinedError()
[docs] def get_configuration_filepath() -> Path: """ Return path to llm-assistant configuration file. """ return get_configuration_folder() / LLM_ASSISTANT_CONFIGURATION_FILENAME
[docs] def get_configuration() -> model.LLMAssistantConfiguration: """ Return configuration object. """ config_filepath = get_configuration_filepath() if not config_filepath.exists(): raise exception.ConfigurationFileDoesNotExistError() with open(config_filepath, "r") as f: return model.LLMAssistantConfiguration.from_dict(**toml.load(f))
[docs] def get_prompt_configuration(prompt_name: str) -> model.PromptConfiguration: """ Get prompt configuration object. It searches the prompt configuration file within the directory specified by runner.prompt_collection_folder setting. Raises: FileNotFoundError: if prompt configuration file is not found. """ config = get_configuration() if config.prompt: prompt_config_filepath = get_absolute_configuration_path( config.prompt.prompt_collection_folder / prompt_name / "config.toml" ) else: raise FileNotFoundError( 2, "File not found", "prompt collection folder is not specified" ) if not prompt_config_filepath.exists(): raise FileNotFoundError(2, "File not found", prompt_config_filepath) with open(prompt_config_filepath) as f: return model.PromptConfiguration(**toml.load(f))
[docs] def get_absolute_configuration_path(path: Path): """ Get absolute path of a configuration parameter. Paths in the configuration file are given relative to the location of the configuration file. This function resolves to its absolute path. """ if path.is_absolute(): return path else: return get_configuration_folder() / path