thunderdome-tools 2.2.0
A utility package for standardized API configurations and tools.
Requires Python: >=3.7

# ThunderTools v. 2.2.0

**ThunderTools** is a Python package designed to streamline development and provide consistent, reusable tools for projects using the Thunderdome Arhitecture. It includes utilities for API configuration, validation, and interaction with external systems, promoting efficient and standardized workflows.

---

## Tools in ThunderTools

1. **ThunderConfig**
   - A comprehensive utility for creating, validating, and serializing API configurations.
   - Supports environment variable integration for dynamic and flexible configuration management.
   - Enables seamless integration with machine learning models, external APIs, and custom workflows.
2. **ThunderLogger**
   - A robust utility for setting up and managing logging configurations.
   - Supports console, file, and syslog handlers with customizable formats.
   - Enables dynamic addition of handlers for greater flexibility in log management.

---

## Installation

Install ThunderTools using pip:

```bash
pip install thunderdome-tools
```

---

# ThunderTools Documentation

## Overview

The **ThunderTools** package is designed to house a variety of tools that support AI-driven applications. Each tool within the package is modular and serves a specific purpose. This documentation provides an in-depth guide to the first two tools in the package: **ThunderConfig** and **ThunderLogger**. Future tools can be added following the structure and principles outlined here.

---

## Table of Contents

1. [ThunderConfig Tool](#1-thunderconfig-tool)
   - [Purpose](#purpose)
   - [Classes](#classes)
     - [InputModel](#1-inputmodel)
     - [ConfigModel](#2-configmodel)
     - [ThunderInput](#3-thunderinput)
     - [ThunderConfigHandler](#4-thunderconfighandler)
   - [Environment Variables](#environment-variables)
   - [Default .env File](#default-env-file)
   - [Essential Provider Keyword Arguments](#essential-provider-keyword-arguments-provider_kwargs)
   - [Usage Examples](#usage-examples)
   - [Error Handling](#error-handling)
2. [ThunderLogger Tool](#2-thunderlogger-tool)
   - [Purpose](#purpose)
   - [Methods](#methods)
     - [setup](#1-setup)
     - [addHandler](#2-addhandler)
     - [Logging Methods](#3-logging-methods)
   - [Environment Variables](#environment-variables)
   - [Usage Examples](#usage-examples)
   - [Error Handling](#error-handling)

---

## 1. ThunderConfig Tool

### Purpose

**ThunderConfig** is a configuration management tool that simplifies the setup and initialization of AI-driven agents. It provides a structured way to handle user inputs, application configurations, and model parameters.

---

### Classes

#### 1. InputModel

Represents the main input for the agent.

**Attributes**:

- `input_value` (`str`): The main input value for the agent, such as a command or query.

#### 2. ConfigModel

Handles the configuration details for the agent.

**Attributes**:

- `user_id` (`str`): The user ID for whom the agent is executed.
- `userkey` (`Optional[str]`): User-specific key for authentication or identification.
- `agentauthtkn` (`Optional[str]`): Agent authentication token for secure agent operations.
- `actions` (`Optional[List[str]]`): List of actions the agent can perform.
- `app` (`Optional[str]`): The application for which the agent is configured.
- `integration_id` (`Optional[str]`): Integration ID for the app.
- `max_tokens` (`Optional[int]`): Maximum tokens for the model.
- `model` (`Optional[str]`): Model name.
- `llm_provider` (`Optional[str]`): Model provider (e.g., OpenAI, Azure, LiteLLM).
- `prompt` (`Optional[str]`): Prompt for the agent.
- `provider_kwargs` (`Optional[Dict[str, Any]]`): Additional provider-specific keyword arguments.
- `temperature` (`Optional[float]`): Temperature for the model.
- `handler` (`Optional[str]`): Specifies the handler logic or endpoint for processing.

#### 3. ThunderInput

A wrapper model that combines `InputModel` and `ConfigModel`.

**Attributes**:

- `input` (`InputModel`): Contains the agent input value.
- `config` (`ConfigModel`): Holds the configuration details for the agent.
- `kwargs` (`Dict`): Additional keyword arguments.

#### 4. ThunderConfigHandler

The main handler class for processing configurations and initializing the LLM.

**Methods**:

1. `__init__(config)`: Initializes the configuration handler.
   - Stores the agent authentication token (`agentauthtkn`).
2. `load_defaults()`: Loads default values from environment variables.
3. `process_config(input_config: ThunderInput) -> Dict[str, Any]`: Processes the input configuration and merges it with defaults.
4. `init_llm()`: Initializes the language model using the processed configuration, handling different providers.

---

### Environment Variables

The following environment variables are used for default configuration:

#### LangChain Variables

- `LANGCHAIN_API_KEY`
- `LANGCHAIN_TRACING_V2`
- `LANGCHAIN_ENDPOINT`
- `LANGCHAIN_PROJECT`

#### Model Configuration

- `DEFAULT_LLM_PROVIDER`
- `DEFAULT_MODEL`
- `DEFAULT_TEMPERATURE`
- `DEFAULT_MAX_TOKENS`
- `DEFAULT_APP`
- `DEFAULT_PROMPT`
- `DEFAULT_ACTIONS`
- `DEFAULT_INTEGRATION`
- `DEFAULT_HANDLER`

#### Provider-Specific Variables

- OpenAI: `OPENAI_API_KEY`, `OPENAI_API_BASE`
- Azure OpenAI: `AZURE_OPENAI_API_KEY`, `AZURE_ENDPOINT`, `AZURE_OPENAI_API_VERSION`, `AZURE_DEPLOYMENT_NAME`
- LiteLLM: `LITELLM_API_KEY`, `LITELLM_BASE_URL`

---

### Default .env File

The following is an example of a default `.env` file for configuring the environment variables:

```
# REQUIRED FOR OPENAI
OPENAI_API_KEY=<OPENAI KEY>
OPENAI_API_BASE=https://api.openai.com/v1

# REQUIRED FOR AZURE
AZURE_OPENAI_API_KEY=<AZURE OPENAI KEY>
AZURE_ENDPOINT=<AZURE ENDPOINT>
AZURE_OPENAI_API_VERSION=<AZURE API VERSION>

# REQUIRED FOR LITELLM
LITELLM_API_KEY=your_litellm_api_key
LITELLM_BASE_URL=https://api.litellm.ai/v1

# REQUIRED (OPENAI or AZURE_OPENAI or LITELLM)
DEFAULT_LLM_PROVIDER=openai
DEFAULT_MODEL=gpt-4o

# OPTIONAL
DEFAULT_TEMPERATURE=0.0
DEFAULT_MAX_TOKENS=16384
```

---

### Essential Provider Keyword Arguments (`provider_kwargs`)

The `provider_kwargs` dictionary can include several essential keyword arguments that are used to configure the language model provider. These arguments will overwrite any default or environment variables if provided. These keyword arguments are optional, and if no `provider_kwargs` are given, the default values or values in the environment will be used.

**Examples of `provider_kwargs`**:

```python
"provider_kwargs": {
    "llm_model": "<YOUR LLM MODEL>",
    "llm_api_key": "<YOUR LLM API KEY>",
    "llm_base_url": "<YOUR LLM BASE URL>",
    "llm_api_version": "<YOUR LLM API VERSION>"
}
```

- `llm_model` (`str`): Specifies the model to be used, overriding the default model.
- `llm_api_key` (`str`): API key for accessing the language model, overriding the default API key.
- `llm_base_url` (`str`): Base URL for the language model API, allowing customization of the endpoint.
- `llm_api_version` (`str`): Version of the language model API to be used, allowing finer control over the API version.

These `provider_kwargs` will take precedence over any defaults or environment variables set for the model configuration, providing greater flexibility in customization.

---

### Usage Examples

#### Basic Configuration Input

```python
from ThunderTools.ThunderConfig import ThunderInput, ThunderConfigHandler

input_data = {
        "input_value": "Tell me about AI"
    }
    config_data = {
        "user_id": "DEFAULT_USER",
        "agentauthtkn": "example_agent_auth_token_67890",
        "llm_provider":"litellm",
        "provider_kwargs": {
            "llm_model": "<YOUR LLM MODEL>",
            "llm_api_key": "<YOUR LLM API KEY>",
            "llm_base_url": "<YOUR LLM BASE URL>"
        }
    }
    thunder_input = ThunderInput(
        input=input_data,
        config=config_data,
        kwargs={}
    )

    handler = ThunderConfigHandler(thunder_input)
    llm = handler.init_llm()
```

---

### Error Handling

1. **Missing Required Fields**:

   - Example: `ValueError: user_id is required in config or .env`
   - Solution: Ensure `user_id` is provided in the configuration or environment variables.

2. **Missing Agent Authentication Token**:

   - Example: `ValueError: agentauthtkn is required for agent authentication`
   - Solution: Ensure `agentauthtkn` is provided in the configuration.

3. **Unsupported Model Provider**:

   - Example: `ValueError: Unsupported model provider: {provider_name}`
   - Solution: Ensure `llm_provider` is one of the supported options (`openai`, `azure`, `litellm`).

4. **Invalid Provider-Specific Configurations**:
   - Example: `provider_kwargs must be a dictionary`
   - Solution: Ensure `provider_kwargs` is a valid dictionary.

---

# 2. ThunderLogger

## Overview

The **ThunderLogger** package provides a modular and easy-to-use logging utility to support application monitoring and debugging. It offers various log handlers and customization options, making it ideal for projects requiring flexible and standardized logging.

## 2. ThunderLogger Tool

### Purpose

**ThunderLogger** is a logging management tool that simplifies setting up and managing logs for applications. It provides multiple handlers, customizable formats, and supports dynamic additions of logging outputs.

---

### Methods

#### 1. `setup`

Initializes the logger with standardized defaults and adds a console handler.

**Parameters**:

- `level` (`str`): The log level (e.g., `"DEBUG"`, `"INFO"`, `"WARNING"`, `"ERROR"`, `"CRITICAL"`) (default: `"INFO"`).
- `fmt` (`Optional[str]`): Log format string (default: `"%(asctime)s [%(levelname)s] %(name)s: %(message)s"`).
- `datefmt` (`Optional[str]`): Date format string (default: `"%Y-%m-%d %H:%M:%S"`).
- `stream` (`sys.stdout`): Stream for console logging (default: `sys.stdout`).
- `handlers` (`Optional[List[Dict[str, Any]]]`): List of handler configurations. Example:

```python
[
    {"handler_name": "file", "filename": "app.log", "fmt": "%(message)s"},
    {"handler_name": "syslog", "address": ("localhost", 514)}
]
```

---

#### 2. `addHandler`

Adds a specific handler to the logger. Supported handlers:

- `"console"`: Adds a StreamHandler (logs to console).
  - Optional kwargs: `stream`, `fmt`, `datefmt`.
- `"file"`: Adds a FileHandler (logs to a file).
  - Optional kwargs: `filename`, `fmt`, `datefmt`.
- `"syslog"`: Adds a SysLogHandler (logs to a syslog server).
  - Optional kwargs: `address`, `fmt`, `datefmt`.

**Parameters**:

- `handler_name` (`str`): The name of the handler to add.
- `kwargs` (`dict`): Additional arguments for the handler.

---

#### 3. Logging Methods

These methods correspond to standard logging levels:

- `debug(msg, *args, **kwargs)`: Logs a message at DEBUG level.
- `info(msg, *args, **kwargs)`: Logs a message at INFO level.
- `warning(msg, *args, **kwargs)`: Logs a message at WARNING level.
- `error(msg, *args, **kwargs)`: Logs a message at ERROR level.
- `critical(msg, *args, **kwargs)`: Logs a message at CRITICAL level.
- `exception(msg, *args, **kwargs)`: Logs an ERROR level message, including traceback information.

---

### Environment Variables

ThunderLogger does not rely on specific environment variables but can integrate seamlessly into environments with pre-defined configurations for logging destinations (e.g., syslog addresses, file paths).

---

### Usage Examples

#### Basic Setup

```python
from ThunderLogger import ThunderLogger

logger = ThunderLogger("my_project")
logger.setup(level="DEBUG")

logger.info("This is an info message.")
logger.debug("Debugging the application.")
```

#### Adding Handlers

```python
from ThunderLogger import ThunderLogger

logger = ThunderLogger("my_project")
logger.setup(level="INFO", fmt="%(levelname)s: %(message)s")

# Adding a file handler
logger.addHandler(
    handler_name="file",
    filename="app.log",
    fmt="%(asctime)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

logger.info("This will also be logged to a file.")
```

#### Custom Handler Configurations

```python
from ThunderLogger import ThunderLogger

logger = ThunderLogger("my_project")
logger.setup(
    level="ERROR",
    handlers=[
        {"handler_name": "file", "filename": "errors.log"},
        {"handler_name": "syslog", "address": ("localhost", 514)}
    ]
)

logger.error("This error will be logged to the file and syslog.")
```

---

### Error Handling

1. **Handler Initialization Failure**:

   - Example: `ValueError: Invalid handler_name: unknown_handler`
   - Solution: Ensure `handler_name` is one of the supported types (`console`, `file`, `syslog`).

2. **File Write Errors**:

   - Example: `PermissionError: [Errno 13] Permission denied: 'restricted.log'`
   - Solution: Check file permissions or use a writable directory.

3. **Syslog Address Issues**:

   - Example: `OSError: [Errno 99] Cannot assign requested address`
   - Solution: Verify the syslog server address and port.

4. **Re-Initialization Warnings**:

   - Example: `Logger is already initialized. Skipping re-setup.`
   - Solution: Avoid calling `setup` multiple times for the same logger.