sunholo 0.71.29__py3-none-any.whl → 0.72.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sunholo/utils/__init__.py +2 -1
- sunholo/utils/config_class.py +207 -0
- {sunholo-0.71.29.dist-info → sunholo-0.72.0.dist-info}/METADATA +2 -2
- {sunholo-0.71.29.dist-info → sunholo-0.72.0.dist-info}/RECORD +8 -7
- {sunholo-0.71.29.dist-info → sunholo-0.72.0.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.71.29.dist-info → sunholo-0.72.0.dist-info}/WHEEL +0 -0
- {sunholo-0.71.29.dist-info → sunholo-0.72.0.dist-info}/entry_points.txt +0 -0
- {sunholo-0.71.29.dist-info → sunholo-0.72.0.dist-info}/top_level.txt +0 -0
sunholo/utils/__init__.py
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
from .config import load_config_key, load_config
|
|
1
|
+
from .config import load_config_key, load_config
|
|
2
|
+
from .config_class import ConfigManager
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import yaml
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
from .timedelta import format_timedelta
|
|
7
|
+
|
|
8
|
+
class ConfigManager:
|
|
9
|
+
def __init__(self, vector_name: str):
|
|
10
|
+
"""
|
|
11
|
+
Initialize the ConfigManager with a vector name.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
vector_name (str): The name of the vector in the configuration files.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
```python
|
|
18
|
+
# Usage example:
|
|
19
|
+
config = ConfigManager("myVector")
|
|
20
|
+
agent = config.vacConfig("agent")
|
|
21
|
+
```
|
|
22
|
+
"""
|
|
23
|
+
self.vector_name = vector_name
|
|
24
|
+
self.config_cache = {}
|
|
25
|
+
self.config_folder = os.getenv("VAC_CONFIG_FOLDER", os.getcwd())
|
|
26
|
+
self.local_config_folder = os.path.join(os.getcwd(), "config")
|
|
27
|
+
self.configs_by_kind = self.load_all_configs()
|
|
28
|
+
|
|
29
|
+
def load_all_configs(self):
|
|
30
|
+
"""
|
|
31
|
+
Load all configuration files from the specified directories into a dictionary.
|
|
32
|
+
Caching is used to avoid reloading files within a 5-minute window.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
dict: A dictionary of configurations grouped by their 'kind' key.
|
|
36
|
+
"""
|
|
37
|
+
from ..logging import log
|
|
38
|
+
|
|
39
|
+
log.debug(f"Loading all configs from folder: {self.config_folder} and local folder: {self.local_config_folder}")
|
|
40
|
+
global_configs_by_kind = self._load_configs_from_folder(self.config_folder)
|
|
41
|
+
local_configs_by_kind = self._load_configs_from_folder(self.local_config_folder)
|
|
42
|
+
|
|
43
|
+
# Merge local configs into global configs
|
|
44
|
+
for kind, local_config in local_configs_by_kind.items():
|
|
45
|
+
if kind in global_configs_by_kind:
|
|
46
|
+
global_configs_by_kind[kind] = self._merge_dicts(global_configs_by_kind[kind], local_config)
|
|
47
|
+
else:
|
|
48
|
+
global_configs_by_kind[kind] = local_config
|
|
49
|
+
|
|
50
|
+
return global_configs_by_kind
|
|
51
|
+
|
|
52
|
+
def _load_configs_from_folder(self, folder):
|
|
53
|
+
"""
|
|
54
|
+
Load all configuration files from a specific folder into a dictionary.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
folder (str): The path of the folder to load configurations from.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
dict: A dictionary of configurations grouped by their 'kind' key.
|
|
61
|
+
"""
|
|
62
|
+
from ..logging import log
|
|
63
|
+
|
|
64
|
+
configs_by_kind = defaultdict(dict)
|
|
65
|
+
current_time = datetime.now()
|
|
66
|
+
|
|
67
|
+
for filename in os.listdir(folder):
|
|
68
|
+
if filename in ["cloudbuild.yaml", "cloud_run_urls.json"]:
|
|
69
|
+
continue
|
|
70
|
+
if filename.endswith(('.yaml', '.yml', '.json')):
|
|
71
|
+
config_file = os.path.join(folder, filename)
|
|
72
|
+
if filename in self.config_cache:
|
|
73
|
+
cached_config, cache_time = self.config_cache[filename]
|
|
74
|
+
time_to_recache = (current_time - cache_time)
|
|
75
|
+
if time_to_recache < timedelta(minutes=5):
|
|
76
|
+
config = cached_config
|
|
77
|
+
else:
|
|
78
|
+
config = self._reload_config_file(config_file, filename, folder == self.local_config_folder)
|
|
79
|
+
else:
|
|
80
|
+
config = self._reload_config_file(config_file, filename, folder == self.local_config_folder)
|
|
81
|
+
kind = config.get('kind')
|
|
82
|
+
if kind:
|
|
83
|
+
configs_by_kind[kind] = config
|
|
84
|
+
else:
|
|
85
|
+
log.warning(f"No 'kind' found in {filename}")
|
|
86
|
+
return configs_by_kind
|
|
87
|
+
|
|
88
|
+
def _reload_config_file(self, config_file, filename, is_local=False):
|
|
89
|
+
"""
|
|
90
|
+
Helper function to load a config file and update the cache.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
config_file (str): The path to the configuration file.
|
|
94
|
+
filename (str): The name of the configuration file.
|
|
95
|
+
is_local (bool): Indicates if the config file is from the local folder.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
dict: The loaded configuration.
|
|
99
|
+
"""
|
|
100
|
+
from ..logging import log
|
|
101
|
+
with open(config_file, 'r') as file:
|
|
102
|
+
if filename.endswith('.json'):
|
|
103
|
+
config = json.load(file)
|
|
104
|
+
else:
|
|
105
|
+
config = yaml.safe_load(file)
|
|
106
|
+
self.config_cache[filename] = (config, datetime.now())
|
|
107
|
+
log.debug(f"Loaded and cached {config_file}")
|
|
108
|
+
if is_local:
|
|
109
|
+
log.warning(f"Local configuration override for {filename}")
|
|
110
|
+
return config
|
|
111
|
+
|
|
112
|
+
def _check_and_reload_configs(self):
|
|
113
|
+
"""
|
|
114
|
+
Check if configurations are older than 5 minutes and reload if necessary.
|
|
115
|
+
"""
|
|
116
|
+
current_time = datetime.now()
|
|
117
|
+
for filename, (config, cache_time) in list(self.config_cache.items()):
|
|
118
|
+
if (current_time - cache_time) >= timedelta(minutes=5):
|
|
119
|
+
config_file_main = os.path.join(self.config_folder, filename)
|
|
120
|
+
config_file_local = os.path.join(self.local_config_folder, filename)
|
|
121
|
+
if os.path.exists(config_file_local):
|
|
122
|
+
self._reload_config_file(config_file_local, filename, is_local=True)
|
|
123
|
+
if os.path.exists(config_file_main):
|
|
124
|
+
self._reload_config_file(config_file_main, filename, is_local=False)
|
|
125
|
+
self.configs_by_kind = self.load_all_configs()
|
|
126
|
+
|
|
127
|
+
def _merge_dicts(self, dict1, dict2):
|
|
128
|
+
"""
|
|
129
|
+
Recursively merge two dictionaries. Local values in dict2 will overwrite global values in dict1.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
dict1 (dict): The global dictionary.
|
|
133
|
+
dict2 (dict): The local dictionary.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
dict: The merged dictionary.
|
|
137
|
+
"""
|
|
138
|
+
for key, value in dict2.items():
|
|
139
|
+
if isinstance(value, dict) and key in dict1 and isinstance(dict1[key], dict):
|
|
140
|
+
dict1[key] = self._merge_dicts(dict1[key], value)
|
|
141
|
+
else:
|
|
142
|
+
dict1[key] = value
|
|
143
|
+
return dict1
|
|
144
|
+
|
|
145
|
+
def vacConfig(self, key: str):
|
|
146
|
+
"""
|
|
147
|
+
Fetch a key from 'vacConfig' kind configuration.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
key (str): The key to fetch from the configuration.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: The value associated with the specified key.
|
|
154
|
+
"""
|
|
155
|
+
self._check_and_reload_configs()
|
|
156
|
+
config = self.configs_by_kind.get('vacConfig')
|
|
157
|
+
if not config:
|
|
158
|
+
return None
|
|
159
|
+
if self.vector_name == 'global':
|
|
160
|
+
return config.get(key)
|
|
161
|
+
vac = config['vac']
|
|
162
|
+
|
|
163
|
+
vac_config = vac.get(self.vector_name)
|
|
164
|
+
if not vac_config:
|
|
165
|
+
return None
|
|
166
|
+
return vac_config.get(key)
|
|
167
|
+
|
|
168
|
+
def promptConfig(self, key: str):
|
|
169
|
+
"""
|
|
170
|
+
Fetch a key from 'promptConfig' kind configuration.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
key (str): The key to fetch from the configuration.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
str: The value associated with the specified key.
|
|
177
|
+
"""
|
|
178
|
+
self._check_and_reload_configs()
|
|
179
|
+
config = self.configs_by_kind.get('promptConfig')
|
|
180
|
+
if not config:
|
|
181
|
+
return None
|
|
182
|
+
prompts = config['prompts']
|
|
183
|
+
prompt_for_vector_name = prompts.get(self.vector_name)
|
|
184
|
+
if not prompt_for_vector_name:
|
|
185
|
+
return None
|
|
186
|
+
return prompt_for_vector_name.get(key)
|
|
187
|
+
|
|
188
|
+
def agentConfig(self, key: str):
|
|
189
|
+
"""
|
|
190
|
+
Fetch a key from 'agentConfig' kind configuration.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
key (str): The key to fetch from the configuration.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
str: The value associated with the specified key.
|
|
197
|
+
"""
|
|
198
|
+
self._check_and_reload_configs()
|
|
199
|
+
config = self.configs_by_kind.get('agentConfig')
|
|
200
|
+
if not config:
|
|
201
|
+
return None
|
|
202
|
+
agents = config.get('agents')
|
|
203
|
+
if key in agents:
|
|
204
|
+
return agents[key]
|
|
205
|
+
else:
|
|
206
|
+
return agents.get("default")
|
|
207
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.72.0
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.72.0.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -98,10 +98,11 @@ sunholo/summarise/__init__.py,sha256=MZk3dblUMODcPb1crq4v-Z508NrFIpkSWNf9FIO8BcU
|
|
|
98
98
|
sunholo/summarise/summarise.py,sha256=C3HhjepTjUhUC8FLk4jMQIBvq1BcORniwuTFHjPVhVo,3784
|
|
99
99
|
sunholo/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
100
100
|
sunholo/tools/web_browser.py,sha256=NgsAeVcndl-vMAbAfIzDJ8eRfCh5LDZan16OCNEKFmI,7094
|
|
101
|
-
sunholo/utils/__init__.py,sha256=
|
|
101
|
+
sunholo/utils/__init__.py,sha256=Hv02T5L2zYWvCso5hzzwm8FQogwBq0OgtUbN_7Quzqc,89
|
|
102
102
|
sunholo/utils/api_key.py,sha256=Ct4bIAQZxzPEw14hP586LpVxBAVi_W9Serpy0BK-7KI,244
|
|
103
103
|
sunholo/utils/big_context.py,sha256=gJIP7_ZL-YSLhOMq8jmFTMqH1wq8eB1NK7oKPeZAq2s,5578
|
|
104
104
|
sunholo/utils/config.py,sha256=5lzO9CkLpDslp66ZwSBC_95aA1FQs-zpiOLi5YaYWbM,8907
|
|
105
|
+
sunholo/utils/config_class.py,sha256=48zEohztqTb13PPYK9SLqWQtrperan-kCVizdhKg8_g,7647
|
|
105
106
|
sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
|
|
106
107
|
sunholo/utils/gcp.py,sha256=uueODEpA-P6O15-t0hmcGC9dONLO_hLfzSsSoQnkUss,4854
|
|
107
108
|
sunholo/utils/gcp_project.py,sha256=0ozs6tzI4qEvEeXb8MxLnCdEVoWKxlM6OH05htj7_tc,1325
|
|
@@ -115,9 +116,9 @@ sunholo/vertex/extensions_class.py,sha256=E0ix4YqFQG9EglKeTmp2-zwuZUA2crileGahAh
|
|
|
115
116
|
sunholo/vertex/init.py,sha256=-w7b9GKsyJnAJpYHYz6_zBUtmeJeLXlEkgOfwoe4DEI,2715
|
|
116
117
|
sunholo/vertex/memory_tools.py,sha256=WpedE5yDZcQiFOFBSOtwr-tRCnCXW9G6aZ01rFDfsMo,6862
|
|
117
118
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
|
118
|
-
sunholo-0.
|
|
119
|
-
sunholo-0.
|
|
120
|
-
sunholo-0.
|
|
121
|
-
sunholo-0.
|
|
122
|
-
sunholo-0.
|
|
123
|
-
sunholo-0.
|
|
119
|
+
sunholo-0.72.0.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
120
|
+
sunholo-0.72.0.dist-info/METADATA,sha256=I_2E5Z5Xq4rQQNgEIp4-WGtlsSXu0PHT2AbuOq8HjIs,6843
|
|
121
|
+
sunholo-0.72.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
122
|
+
sunholo-0.72.0.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
123
|
+
sunholo-0.72.0.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
124
|
+
sunholo-0.72.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|