forked from Miyamura80/Python-Template
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathglobal_config.py
More file actions
142 lines (118 loc) · 5.15 KB
/
Copy pathglobal_config.py
File metadata and controls
142 lines (118 loc) · 5.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import os
import yaml
from pathlib import Path
from dotenv import load_dotenv, dotenv_values
import warnings
from loguru import logger
import re
# Get the path to the root directory (one level up from global_config)
root_dir = Path(__file__).parent.parent
# Load .env file from the root directory
load_dotenv(dotenv_path=root_dir / ".env")
# Check if .env file has been properly loaded
env_values = dotenv_values(root_dir / ".env")
is_local = os.getenv("GITHUB_ACTIONS") != "true"
if not env_values and is_local:
warnings.warn(".env file not found or empty", UserWarning)
OPENAI_O_SERIES_PATTERN = r"o(\d+)(-mini)?"
class DictWrapper:
def __init__(self, data):
for key, value in data.items():
if isinstance(value, dict):
setattr(self, key, DictWrapper(value))
else:
setattr(self, key, value)
class Config:
_env_keys = [
"DEV_ENV",
"OPENAI_API_KEY",
"ANTHROPIC_API_KEY",
"GROQ_API_KEY",
"PERPLEXITY_API_KEY",
"GEMINI_API_KEY",
]
def __init__(self):
def recursive_update(default, override):
for key, value in override.items():
if isinstance(value, dict) and isinstance(default.get(key), dict):
recursive_update(default[key], value)
else:
default[key] = value
return default
with open("global_config/global_config.yaml", "r") as file:
config_data = yaml.safe_load(file)
# Load the local .gitignored custom global config if it exists
custom_config_path = root_dir / ".global_config.yaml"
if custom_config_path.exists():
with open(custom_config_path, "r") as file:
custom_config_data = yaml.safe_load(file)
# Only create and show warning if there's custom config data
if custom_config_data:
# Update the config_data with custom values
config_data = recursive_update(config_data, custom_config_data)
# Warning message
warning_msg = "\033[33m❗️ Overwriting default global_config.yaml with .global_config.yaml\033[0m"
if config_data["logging"]["verbose"]:
warning_msg += f"\033[33mCustom .global_config.yaml values:\n---\n{yaml.dump(custom_config_data, default_flow_style=False)}\033[0m"
logger.warning(warning_msg)
for key, value in config_data.items():
if isinstance(value, dict):
setattr(self, key, DictWrapper(value))
else:
setattr(self, key, value)
# Assert we found all necessary keys
for key in self._env_keys:
if os.environ.get(key) is None:
raise ValueError(f"Environment variable {key} not found")
else:
setattr(self, key, os.environ.get(key))
# Figure out runtime environment
self.is_local = os.getenv("GITHUB_ACTIONS") != "true"
self.running_on = "🖥️ local" if self.is_local else "☁️ CI"
def __getattr__(self, name):
raise AttributeError(f"'Config' object has no attribute '{name}'")
def to_dict(self):
def unwrap(obj):
if isinstance(obj, DictWrapper):
return {k: unwrap(v) for k, v in obj.__dict__.items()}
elif isinstance(obj, list):
return [unwrap(item) for item in obj]
else:
return obj
return {k: unwrap(v) for k, v in self.__dict__.items()}
def llm_api_key(self, model_name: str | None = None) -> str:
"""Returns the appropriate API key based on the model name."""
model_identifier = model_name or self.model_name
if "gpt" in model_identifier.lower() or re.match(
OPENAI_O_SERIES_PATTERN, model_identifier.lower()
):
return self.OPENAI_API_KEY
elif (
"claude" in model_identifier.lower()
or "anthropic" in model_identifier.lower()
):
return self.ANTHROPIC_API_KEY
elif "groq" in model_identifier.lower():
return self.GROQ_API_KEY
elif "perplexity" in model_identifier.lower():
return self.PERPLEXITY_API_KEY
elif "gemini" in model_identifier.lower():
return self.GEMINI_API_KEY
else:
raise ValueError(f"No API key configured for model: {model_identifier}")
def api_base(self, model_name: str) -> str | None:
"""Returns the Helicone link for the model."""
if "gpt" in model_name.lower() or re.match(
OPENAI_O_SERIES_PATTERN, model_name.lower()
):
return "https://oai.hconeai.com/v1"
elif "groq" in model_name.lower():
return "https://groq.helicone.ai/openai/v1"
elif "perplexity" in model_name.lower():
return "https://perplexity.helicone.ai"
elif "gemini" in model_name.lower():
return "https://generativelanguage.googleapis.com/v1beta/openai/"
else:
logger.error(f"Helicone link not found for model: {model_name}")
# Create a singleton instance
global_config = Config()