ghmk's picture
Initial deployment of Character Forge
5b6e956

settings.py

Purpose

Centralized configuration management for the entire Nano Banana Streamlit application. Single source of truth for all constants, paths, and environment-dependent settings.

Responsibilities

  • Define all project paths (output directories, log files)
  • Manage API keys and credentials
  • Configure backend URLs and timeouts
  • Define generation parameters (aspect ratios, temperatures)
  • Provide character forge-specific settings
  • Configure logging parameters
  • Define UI constants
  • Provide helper methods for common configuration tasks

Dependencies

Imports

  • os - Environment variable access
  • pathlib.Path - Path manipulation
  • typing.Optional - Type hints

Used By

  • app.py - Gets API keys and output directory
  • All services - Import constants for generation
  • All UI components - Import display constants
  • core/backend_router.py - Backend URLs and timeouts
  • Logging setup - Log configuration

Public Interface

Class: Settings

Static class (no instantiation needed) providing configuration through class methods and properties.

Project Paths

Settings.PROJECT_ROOT         # Path to project root
Settings.OUTPUT_DIR           # Main output directory
Settings.CHARACTER_SHEETS_DIR # Character sheet outputs
Settings.WARDROBE_CHANGES_DIR # Wardrobe change outputs
Settings.COMPOSITIONS_DIR     # Composition outputs
Settings.STANDARD_DIR         # Standard generation outputs
Settings.LOG_FILE             # Log file path

API Configuration

Settings.get_gemini_api_key() -> Optional[str]
    # Returns Gemini API key from GEMINI_API_KEY env var

Settings.OMNIGEN2_BASE_URL    # OmniGen2 server URL
Settings.BACKEND_TIMEOUT      # Request timeout in seconds

Generation Parameters

Settings.ASPECT_RATIOS           # Dict of display name -> ratio
Settings.DEFAULT_ASPECT_RATIO    # Default selection
Settings.DEFAULT_TEMPERATURE     # Default temp (0.4)
Settings.MIN_TEMPERATURE         # Min temp (0.0)
Settings.MAX_TEMPERATURE         # Max temp (1.0)
Settings.TEMPERATURE_STEP        # Slider step (0.05)

Character Forge Settings

Settings.PORTRAIT_ASPECT_RATIO       # "3:4" for portraits
Settings.BODY_ASPECT_RATIO           # "9:16" for body shots
Settings.PORTRAIT_TEMPERATURE        # 0.35 (lower for consistency)
Settings.BODY_TEMPERATURE            # 0.5 (variety)
Settings.CHARACTER_SHEET_SPACING     # 20px between rows
Settings.CHARACTER_SHEET_BACKGROUND  # "#2C2C2C" dark gray
Settings.MAX_RETRIES                 # 3 attempts
Settings.RETRY_BASE_DELAY            # 2s (exponential backoff)
Settings.RATE_LIMIT_DELAY_MIN        # 2.0s
Settings.RATE_LIMIT_DELAY_MAX        # 3.0s

Logging Configuration

Settings.LOG_LEVEL         # "INFO"
Settings.LOG_FORMAT        # Log message format string
Settings.LOG_DATE_FORMAT   # Date format string
Settings.LOG_MAX_BYTES     # 10MB per file
Settings.LOG_BACKUP_COUNT  # 5 backup files

UI Configuration

Settings.MAX_IMAGE_UPLOAD_SIZE  # 20MB
Settings.PREVIEW_IMAGE_WIDTH    # 512px
Settings.MAX_HISTORY_ITEMS      # 20 recent generations

Composition Assistant Settings

Settings.IMAGE_TYPES       # List of image type options
Settings.SHOT_TYPES        # List of shot type options
Settings.CAMERA_ANGLES     # List of camera angle options
Settings.LIGHTING_OPTIONS  # List of lighting options

Backend Types

Settings.BACKEND_GEMINI      # "Gemini API (Cloud)"
Settings.BACKEND_OMNIGEN2    # "OmniGen2 (Local)"
Settings.AVAILABLE_BACKENDS  # List of both

Helper Methods

Settings.get_aspect_ratio_value(display_name: str) -> str
    # "16:9 (1344x768)" → "16:9"

Settings.is_gemini_configured() -> bool
    # Check if Gemini API key is set

Settings.validate_temperature(temperature: float) -> float
    # Clamp temperature to valid range

Usage Examples

Get API Key

from config.settings import Settings

api_key = Settings.get_gemini_api_key()
if api_key:
    # Use API key
    pass
else:
    # Prompt user for API key
    pass

Save Generation Output

from config.settings import Settings
from datetime import datetime

# Create filename
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"character_{timestamp}.png"

# Save to appropriate directory
output_path = Settings.CHARACTER_SHEETS_DIR / filename
image.save(output_path)

Validate Temperature

from config.settings import Settings

user_temp = 1.5  # Invalid - too high
valid_temp = Settings.validate_temperature(user_temp)  # Returns 1.0

Environment Variables

Required

  • None - App runs with defaults

Optional

Known Limitations

  • API key only loaded from environment, not from config file
  • No runtime configuration reloading (requires restart)
  • No user-specific configuration (multi-user scenarios)
  • Hardcoded OmniGen2 URL (not configurable without code change)

Future Improvements

  • Support config file (.env, .toml, .yaml)
  • Add user profiles with different defaults
  • Make all URLs/ports configurable
  • Add validation for all settings on startup
  • Add settings UI page for runtime changes
  • Support multiple OmniGen2 instances (load balancing)

Testing

  • Verify all paths are created on import
  • Test get_gemini_api_key() with and without env var
  • Test validate_temperature() with various inputs
  • Test get_aspect_ratio_value() with all display names
  • Verify all constants are accessible

Related Files

  • app.py - Main app imports this first
  • All services - Use constants from here
  • All UI pages - Use UI constants from here
  • core/backend_router.py - Uses backend URLs
  • utils/logging_utils.py - Uses logging configuration

Security Considerations

  • API keys read from environment (not hardcoded)
  • No API keys written to logs
  • Output directory permissions should be restricted in production

Change History

  • 2025-10-23: Initial creation for Streamlit migration
    • All constants from Gradio version migrated
    • Added comprehensive documentation
    • Added helper methods for common tasks