sunholo 0.71.29__py3-none-any.whl → 0.73.2__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/agents/dispatch_to_qa.py +10 -7
- sunholo/agents/langserve.py +1 -1
- sunholo/agents/route.py +24 -9
- sunholo/cli/chat_vac.py +20 -60
- sunholo/cli/cli.py +3 -3
- sunholo/cli/embedder.py +2 -1
- sunholo/components/retriever.py +2 -2
- sunholo/gcs/add_file.py +19 -11
- sunholo/invoke/__init__.py +1 -0
- sunholo/invoke/invoke_vac_utils.py +151 -0
- sunholo/langfuse/prompts.py +9 -3
- sunholo/llamaindex/import_files.py +8 -7
- sunholo/streaming/langserve.py +4 -1
- sunholo/utils/__init__.py +2 -1
- sunholo/utils/config.py +1 -1
- sunholo/utils/config_class.py +219 -0
- sunholo/vertex/extensions_class.py +179 -64
- sunholo/vertex/memory_tools.py +1 -1
- {sunholo-0.71.29.dist-info → sunholo-0.73.2.dist-info}/METADATA +4 -3
- {sunholo-0.71.29.dist-info → sunholo-0.73.2.dist-info}/RECORD +24 -22
- sunholo/vertex/extensions.py +0 -326
- {sunholo-0.71.29.dist-info → sunholo-0.73.2.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.71.29.dist-info → sunholo-0.73.2.dist-info}/WHEEL +0 -0
- {sunholo-0.71.29.dist-info → sunholo-0.73.2.dist-info}/entry_points.txt +0 -0
- {sunholo-0.71.29.dist-info → sunholo-0.73.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
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
|
+
Requires a local config/ folder holding your configuration files or the env var VAC_CONFIG_FOLDER to be set.
|
|
13
|
+
|
|
14
|
+
Read more at: https://dev.sunholo.com/docs/config
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
vector_name (str): The name of the vector in the configuration files.
|
|
18
|
+
|
|
19
|
+
Example:
|
|
20
|
+
```python
|
|
21
|
+
# Usage example:
|
|
22
|
+
config = ConfigManager("my_vac")
|
|
23
|
+
agent = config.vacConfig("agent")
|
|
24
|
+
```
|
|
25
|
+
"""
|
|
26
|
+
local_config_folder = os.path.join(os.getcwd(), "config")
|
|
27
|
+
if os.path.isdir(local_config_folder):
|
|
28
|
+
print(f"Found local config folder {local_config_folder} - will overwrite any global configurations")
|
|
29
|
+
else:
|
|
30
|
+
local_config_folder = None
|
|
31
|
+
if os.getenv("VAC_CONFIG_FOLDER") is None and local_config_folder is None:
|
|
32
|
+
raise ValueError(f"Must have either a local config/ folder in this dir ({os.getcwd()}/config/) or a folder specified via the VAC_CONFIG_FOLDER environment variable, or both.")
|
|
33
|
+
|
|
34
|
+
self.vector_name = vector_name
|
|
35
|
+
self.config_cache = {}
|
|
36
|
+
self.config_folder = os.getenv("VAC_CONFIG_FOLDER", os.getcwd())
|
|
37
|
+
self.local_config_folder = local_config_folder
|
|
38
|
+
self.configs_by_kind = self.load_all_configs()
|
|
39
|
+
|
|
40
|
+
def load_all_configs(self):
|
|
41
|
+
"""
|
|
42
|
+
Load all configuration files from the specified directories into a dictionary.
|
|
43
|
+
Caching is used to avoid reloading files within a 5-minute window.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
dict: A dictionary of configurations grouped by their 'kind' key.
|
|
47
|
+
"""
|
|
48
|
+
from ..logging import log
|
|
49
|
+
|
|
50
|
+
log.debug(f"Loading all configs from folder: {self.config_folder} and local folder: {self.local_config_folder}")
|
|
51
|
+
global_configs_by_kind = self._load_configs_from_folder(self.config_folder)
|
|
52
|
+
|
|
53
|
+
if self.local_config_folder:
|
|
54
|
+
local_configs_by_kind = self._load_configs_from_folder(self.local_config_folder)
|
|
55
|
+
# Merge local configs into global configs
|
|
56
|
+
for kind, local_config in local_configs_by_kind.items():
|
|
57
|
+
if kind in global_configs_by_kind:
|
|
58
|
+
global_configs_by_kind[kind] = self._merge_dicts(global_configs_by_kind[kind], local_config)
|
|
59
|
+
else:
|
|
60
|
+
global_configs_by_kind[kind] = local_config
|
|
61
|
+
|
|
62
|
+
return global_configs_by_kind
|
|
63
|
+
|
|
64
|
+
def _load_configs_from_folder(self, folder):
|
|
65
|
+
"""
|
|
66
|
+
Load all configuration files from a specific folder into a dictionary.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
folder (str): The path of the folder to load configurations from.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
dict: A dictionary of configurations grouped by their 'kind' key.
|
|
73
|
+
"""
|
|
74
|
+
from ..logging import log
|
|
75
|
+
|
|
76
|
+
configs_by_kind = defaultdict(dict)
|
|
77
|
+
current_time = datetime.now()
|
|
78
|
+
|
|
79
|
+
for filename in os.listdir(folder):
|
|
80
|
+
if filename in ["cloudbuild.yaml", "cloud_run_urls.json"]:
|
|
81
|
+
continue
|
|
82
|
+
if filename.endswith(('.yaml', '.yml', '.json')):
|
|
83
|
+
config_file = os.path.join(folder, filename)
|
|
84
|
+
if filename in self.config_cache:
|
|
85
|
+
cached_config, cache_time = self.config_cache[filename]
|
|
86
|
+
time_to_recache = (current_time - cache_time)
|
|
87
|
+
if time_to_recache < timedelta(minutes=5):
|
|
88
|
+
config = cached_config
|
|
89
|
+
else:
|
|
90
|
+
config = self._reload_config_file(config_file, filename, folder == self.local_config_folder)
|
|
91
|
+
else:
|
|
92
|
+
config = self._reload_config_file(config_file, filename, folder == self.local_config_folder)
|
|
93
|
+
kind = config.get('kind')
|
|
94
|
+
if kind:
|
|
95
|
+
configs_by_kind[kind] = config
|
|
96
|
+
else:
|
|
97
|
+
log.warning(f"No 'kind' found in {filename}")
|
|
98
|
+
return configs_by_kind
|
|
99
|
+
|
|
100
|
+
def _reload_config_file(self, config_file, filename, is_local=False):
|
|
101
|
+
"""
|
|
102
|
+
Helper function to load a config file and update the cache.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
config_file (str): The path to the configuration file.
|
|
106
|
+
filename (str): The name of the configuration file.
|
|
107
|
+
is_local (bool): Indicates if the config file is from the local folder.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
dict: The loaded configuration.
|
|
111
|
+
"""
|
|
112
|
+
from ..logging import log
|
|
113
|
+
with open(config_file, 'r') as file:
|
|
114
|
+
if filename.endswith('.json'):
|
|
115
|
+
config = json.load(file)
|
|
116
|
+
else:
|
|
117
|
+
config = yaml.safe_load(file)
|
|
118
|
+
self.config_cache[filename] = (config, datetime.now())
|
|
119
|
+
log.debug(f"Loaded and cached {config_file}")
|
|
120
|
+
if is_local:
|
|
121
|
+
log.warning(f"Local configuration override for {filename}")
|
|
122
|
+
return config
|
|
123
|
+
|
|
124
|
+
def _check_and_reload_configs(self):
|
|
125
|
+
"""
|
|
126
|
+
Check if configurations are older than 5 minutes and reload if necessary.
|
|
127
|
+
"""
|
|
128
|
+
current_time = datetime.now()
|
|
129
|
+
for filename, (config, cache_time) in list(self.config_cache.items()):
|
|
130
|
+
if (current_time - cache_time) >= timedelta(minutes=5):
|
|
131
|
+
config_file_main = os.path.join(self.config_folder, filename)
|
|
132
|
+
config_file_local = os.path.join(self.local_config_folder, filename)
|
|
133
|
+
if os.path.exists(config_file_local):
|
|
134
|
+
self._reload_config_file(config_file_local, filename, is_local=True)
|
|
135
|
+
if os.path.exists(config_file_main):
|
|
136
|
+
self._reload_config_file(config_file_main, filename, is_local=False)
|
|
137
|
+
self.configs_by_kind = self.load_all_configs()
|
|
138
|
+
|
|
139
|
+
def _merge_dicts(self, dict1, dict2):
|
|
140
|
+
"""
|
|
141
|
+
Recursively merge two dictionaries. Local values in dict2 will overwrite global values in dict1.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
dict1 (dict): The global dictionary.
|
|
145
|
+
dict2 (dict): The local dictionary.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
dict: The merged dictionary.
|
|
149
|
+
"""
|
|
150
|
+
for key, value in dict2.items():
|
|
151
|
+
if isinstance(value, dict) and key in dict1 and isinstance(dict1[key], dict):
|
|
152
|
+
dict1[key] = self._merge_dicts(dict1[key], value)
|
|
153
|
+
else:
|
|
154
|
+
dict1[key] = value
|
|
155
|
+
return dict1
|
|
156
|
+
|
|
157
|
+
def vacConfig(self, key: str):
|
|
158
|
+
"""
|
|
159
|
+
Fetch a key from 'vacConfig' kind configuration.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
key (str): The key to fetch from the configuration.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
str: The value associated with the specified key.
|
|
166
|
+
"""
|
|
167
|
+
self._check_and_reload_configs()
|
|
168
|
+
config = self.configs_by_kind.get('vacConfig')
|
|
169
|
+
if not config:
|
|
170
|
+
return None
|
|
171
|
+
if self.vector_name == 'global':
|
|
172
|
+
return config.get(key)
|
|
173
|
+
vac = config['vac']
|
|
174
|
+
|
|
175
|
+
vac_config = vac.get(self.vector_name)
|
|
176
|
+
if not vac_config:
|
|
177
|
+
return None
|
|
178
|
+
return vac_config.get(key)
|
|
179
|
+
|
|
180
|
+
def promptConfig(self, key: str):
|
|
181
|
+
"""
|
|
182
|
+
Fetch a key from 'promptConfig' kind configuration.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
key (str): The key to fetch from the configuration.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
str: The value associated with the specified key.
|
|
189
|
+
"""
|
|
190
|
+
self._check_and_reload_configs()
|
|
191
|
+
config = self.configs_by_kind.get('promptConfig')
|
|
192
|
+
if not config:
|
|
193
|
+
return None
|
|
194
|
+
prompts = config['prompts']
|
|
195
|
+
prompt_for_vector_name = prompts.get(self.vector_name)
|
|
196
|
+
if not prompt_for_vector_name:
|
|
197
|
+
return None
|
|
198
|
+
return prompt_for_vector_name.get(key)
|
|
199
|
+
|
|
200
|
+
def agentConfig(self, key: str):
|
|
201
|
+
"""
|
|
202
|
+
Fetch a key from 'agentConfig' kind configuration.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
key (str): The key to fetch from the configuration.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
str: The value associated with the specified key.
|
|
209
|
+
"""
|
|
210
|
+
self._check_and_reload_configs()
|
|
211
|
+
config = self.configs_by_kind.get('agentConfig')
|
|
212
|
+
if not config:
|
|
213
|
+
return None
|
|
214
|
+
agents = config.get('agents')
|
|
215
|
+
if key in agents:
|
|
216
|
+
return agents[key]
|
|
217
|
+
else:
|
|
218
|
+
return agents.get("default")
|
|
219
|
+
|
|
@@ -10,8 +10,46 @@ from ..utils.parsers import validate_extension_id
|
|
|
10
10
|
import base64
|
|
11
11
|
import json
|
|
12
12
|
from io import StringIO
|
|
13
|
+
import os
|
|
13
14
|
|
|
14
15
|
class VertexAIExtensions:
|
|
16
|
+
"""
|
|
17
|
+
Example
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from sunholo.vertex import VertexAIExtensions
|
|
21
|
+
vex = VertexAIExtensions()
|
|
22
|
+
vex.list_extensions()
|
|
23
|
+
# [{'resource_name': 'projects/374404277595/locations/us-central1/extensions/770924776838397952',
|
|
24
|
+
# 'display_name': 'Code Interpreter',
|
|
25
|
+
# 'description': 'N/A'}]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Creating an extension example as per:
|
|
29
|
+
https://cloud.google.com/vertex-ai/generative-ai/docs/extensions/create-extension
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
## validates before upload
|
|
33
|
+
vex.upload_openapi_file("your-extension-name.yaml")
|
|
34
|
+
vex.openapi_file_gcs
|
|
35
|
+
# 'gs://your-extensions-bucket/your-extension-name.yaml'
|
|
36
|
+
|
|
37
|
+
## load in examples to be used by creation later
|
|
38
|
+
vex.load_tool_use_examples('your-examples.yaml')
|
|
39
|
+
|
|
40
|
+
vex.create_extension(
|
|
41
|
+
"My New Extension",
|
|
42
|
+
description="Querying the VAC above my database",
|
|
43
|
+
service_account='sa-serviceaccount@my-project.iam.gserviceaccount.com')
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Call the extension
|
|
47
|
+
```python
|
|
48
|
+
operation_params = {"input": {"question":"This needs to be in same schema as your openapi spec"}
|
|
49
|
+
vex.execute_extension("an_operation_id_from_your_openai_spec",
|
|
50
|
+
operation_params = operation_params)
|
|
51
|
+
```
|
|
52
|
+
"""
|
|
15
53
|
def __init__(self):
|
|
16
54
|
if extensions is None:
|
|
17
55
|
raise ImportError("VertexAIExtensions needs vertexai.previewextensions to be installed. Install via `pip install sunholo[gcp]`")
|
|
@@ -27,6 +65,10 @@ class VertexAIExtensions:
|
|
|
27
65
|
"""
|
|
28
66
|
self.IMAGE_FILE_EXTENSIONS = set(["jpg", "jpeg", "png"])
|
|
29
67
|
self.location = "us-central1"
|
|
68
|
+
self.openapi_file_gcs = None
|
|
69
|
+
self.tool_use_examples = None
|
|
70
|
+
self.manifest = {}
|
|
71
|
+
self.created_extensions = []
|
|
30
72
|
|
|
31
73
|
def list_extensions(self):
|
|
32
74
|
the_list = extensions.Extension.list()
|
|
@@ -40,92 +82,165 @@ class VertexAIExtensions:
|
|
|
40
82
|
})
|
|
41
83
|
|
|
42
84
|
return extensions_list
|
|
85
|
+
|
|
86
|
+
def validate_openapi(self, filename):
|
|
87
|
+
try:
|
|
88
|
+
from openapi_spec_validator import validate
|
|
89
|
+
from openapi_spec_validator.readers import read_from_filename
|
|
90
|
+
except ImportError:
|
|
91
|
+
raise ImportError("Must have openapi-spec-validator installed - install via `pip install sunholo[tools]`")
|
|
92
|
+
|
|
93
|
+
spec_dict, spec_url = read_from_filename(filename)
|
|
94
|
+
validate(spec_dict)
|
|
95
|
+
|
|
96
|
+
def upload_to_gcs(self, filename):
|
|
97
|
+
if not os.getenv('EXTENSIONS_BUCKET'):
|
|
98
|
+
raise ValueError('Please specify env var EXTENSIONS_BUCKET for location to upload openapi spec')
|
|
43
99
|
|
|
100
|
+
from ..gcs.add_file import add_file_to_gcs
|
|
101
|
+
file_base = os.path.basename(filename)
|
|
44
102
|
|
|
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
|
-
|
|
103
|
+
self_uri = add_file_to_gcs(file_base, bucket_filepath=file_base)
|
|
104
|
+
|
|
105
|
+
return self_uri
|
|
106
|
+
|
|
107
|
+
def upload_openapi_file(self, filename: str):
|
|
108
|
+
self.validate_openapi(filename)
|
|
109
|
+
|
|
110
|
+
self.openapi_file_gcs = self.upload_to_gcs(filename)
|
|
111
|
+
|
|
112
|
+
def load_tool_use_examples(self, filename: str):
|
|
113
|
+
import yaml
|
|
114
|
+
|
|
115
|
+
with open(filename, 'r') as file:
|
|
116
|
+
self.tool_use_examples = yaml.safe_load(file)
|
|
117
|
+
|
|
118
|
+
# google.cloud.aiplatform_v1beta1.types.ToolUseExample
|
|
119
|
+
return self.tool_use_examples
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def update_tool_use_examples_via_patch(self):
|
|
123
|
+
import requests
|
|
124
|
+
import json
|
|
125
|
+
from google.auth import default
|
|
126
|
+
from google.auth.transport.requests import Request
|
|
127
|
+
|
|
128
|
+
extension = self.created_extension
|
|
129
|
+
if extension is None:
|
|
130
|
+
raise ValueError("Need to create the extension first")
|
|
131
|
+
|
|
132
|
+
# Get the access token using Google authentication
|
|
133
|
+
credentials, project_id = default()
|
|
134
|
+
credentials.refresh(Request())
|
|
135
|
+
access_token = credentials.token
|
|
136
|
+
|
|
137
|
+
ENDPOINT=f"{self.location}-aiplatform.googleapis.com"
|
|
138
|
+
URL=f"https://{ENDPOINT}/v1beta1"
|
|
139
|
+
|
|
140
|
+
extension_id = self.created_extension.resource_name
|
|
141
|
+
|
|
142
|
+
# Define the URL and extension ID
|
|
143
|
+
url = f"{URL}/{extension_id}"
|
|
144
|
+
log.info(f"PATCH {url}")
|
|
145
|
+
headers = {
|
|
146
|
+
"Authorization": f"Bearer {access_token}",
|
|
147
|
+
"Content-Type": "application/json"
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# Define the payload
|
|
151
|
+
payload = {
|
|
152
|
+
"toolUseExamples": self.tool_use_examples['tool_use_examples']
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
# Make the PATCH request
|
|
156
|
+
response = requests.patch(
|
|
157
|
+
url,
|
|
158
|
+
headers=headers,
|
|
159
|
+
params={"update_mask": "toolUseExamples"},
|
|
160
|
+
data=json.dumps(payload)
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Check the response
|
|
164
|
+
if response.status_code == 200:
|
|
165
|
+
log.info("Tool use examples updated successfully.")
|
|
166
|
+
else:
|
|
167
|
+
log.info(f"Failed to update tool use examples. Status code: {response.status_code}, Response: {response.text}")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def create_extension_manifest(self,
|
|
171
|
+
display_name,
|
|
172
|
+
description,
|
|
173
|
+
open_api_gcs_uri: str,
|
|
174
|
+
service_account: str):
|
|
175
|
+
|
|
176
|
+
self.manifest = {
|
|
177
|
+
"name": display_name,
|
|
178
|
+
"description": description,
|
|
84
179
|
"apiSpec": {
|
|
85
|
-
"openApiGcsUri":
|
|
180
|
+
"openApiGcsUri": open_api_gcs_uri,
|
|
86
181
|
},
|
|
87
182
|
"authConfig": {
|
|
88
183
|
"authType": "OAUTH",
|
|
89
|
-
"oauthConfig": {"service_account":
|
|
184
|
+
"oauthConfig": {"service_account": service_account}
|
|
90
185
|
}
|
|
91
|
-
},
|
|
92
|
-
"toolUseExamples": tool_use_examples,
|
|
93
186
|
}
|
|
94
187
|
|
|
95
|
-
|
|
96
|
-
|
|
188
|
+
return self.manifest
|
|
189
|
+
|
|
190
|
+
def create_extension(self,
|
|
191
|
+
display_name: str,
|
|
192
|
+
description: str,
|
|
193
|
+
open_api_file: str = None,
|
|
194
|
+
tool_example_file: str = None,
|
|
195
|
+
runtime_config: dict = None,
|
|
196
|
+
service_account: str = None):
|
|
197
|
+
|
|
97
198
|
project_id = get_gcp_project()
|
|
98
199
|
extension_name = f"projects/{project_id}/locations/us-central1/extensions/{validate_extension_id(display_name)}"
|
|
99
200
|
|
|
201
|
+
if open_api_file:
|
|
202
|
+
self.upload_openapi_file(open_api_file)
|
|
203
|
+
|
|
204
|
+
manifest = self.create_extension_manifest(
|
|
205
|
+
display_name,
|
|
206
|
+
description,
|
|
207
|
+
open_api_gcs_uri = self.openapi_file_gcs,
|
|
208
|
+
service_account = service_account,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
if tool_example_file:
|
|
212
|
+
self.load_tool_use_examples(tool_example_file)
|
|
213
|
+
|
|
100
214
|
extension = extensions.Extension.create(
|
|
101
215
|
extension_name=extension_name,
|
|
102
216
|
display_name=display_name,
|
|
103
217
|
description=description,
|
|
104
|
-
runtime_config=runtime_config or None,
|
|
105
|
-
manifest=
|
|
106
|
-
|
|
107
|
-
"description": llm_description or description,
|
|
108
|
-
"api_spec": {
|
|
109
|
-
"open_api_gcs_uri": open_api_gcs_uri
|
|
110
|
-
},
|
|
111
|
-
"auth_config": {
|
|
112
|
-
"auth_type": "GOOGLE_SERVICE_ACCOUNT_AUTH",
|
|
113
|
-
"google_service_account_config": service_account or {},
|
|
114
|
-
},
|
|
115
|
-
},
|
|
218
|
+
runtime_config=runtime_config or None, # sets things like what bucket will be used
|
|
219
|
+
manifest=manifest,
|
|
220
|
+
#tool_use_examples=self.tool_use_examples
|
|
116
221
|
)
|
|
117
222
|
log.info(f"Created Vertex Extension: {extension_name}")
|
|
223
|
+
|
|
224
|
+
self.created_extension = extension
|
|
225
|
+
|
|
226
|
+
if tool_example_file:
|
|
227
|
+
self.update_tool_use_examples_via_patch()
|
|
118
228
|
|
|
119
|
-
return extension
|
|
229
|
+
return extension.resource_name
|
|
120
230
|
|
|
121
|
-
def execute_extension(self, operation_id: str, operation_params: dict, extension_id: str):
|
|
231
|
+
def execute_extension(self, operation_id: str, operation_params: dict, extension_id: str=None):
|
|
122
232
|
init_vertex(location=self.location)
|
|
123
233
|
|
|
124
|
-
if not extension_id
|
|
125
|
-
|
|
126
|
-
extension_name
|
|
127
|
-
|
|
128
|
-
|
|
234
|
+
if not extension_id:
|
|
235
|
+
extension_name = self.created_extension.resource_name
|
|
236
|
+
if extension_name is None:
|
|
237
|
+
raise ValueError("Must specify extension_id or init one with class")
|
|
238
|
+
else:
|
|
239
|
+
if not extension_id.startswith("projects/"):
|
|
240
|
+
project_id = get_gcp_project()
|
|
241
|
+
extension_name = f"projects/{project_id}/locations/{self.location}/extensions/{extension_id}"
|
|
242
|
+
else:
|
|
243
|
+
extension_name = extension_id
|
|
129
244
|
|
|
130
245
|
extension = extensions.Extension(extension_name)
|
|
131
246
|
|
sunholo/vertex/memory_tools.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.73.2
|
|
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.73.2.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -87,7 +87,7 @@ Requires-Dist: google-api-python-client ; extra == 'gcp'
|
|
|
87
87
|
Requires-Dist: google-cloud-alloydb-connector[pg8000] ; extra == 'gcp'
|
|
88
88
|
Requires-Dist: google-auth-httplib2 ; extra == 'gcp'
|
|
89
89
|
Requires-Dist: google-auth-oauthlib ; extra == 'gcp'
|
|
90
|
-
Requires-Dist: google-cloud-aiplatform ; extra == 'gcp'
|
|
90
|
+
Requires-Dist: google-cloud-aiplatform >=1.58.0 ; extra == 'gcp'
|
|
91
91
|
Requires-Dist: google-cloud-bigquery ; extra == 'gcp'
|
|
92
92
|
Requires-Dist: google-cloud-build ; extra == 'gcp'
|
|
93
93
|
Requires-Dist: google-cloud-service-control ; extra == 'gcp'
|
|
@@ -119,6 +119,7 @@ Requires-Dist: pytesseract ; extra == 'pipeline'
|
|
|
119
119
|
Requires-Dist: tabulate ; extra == 'pipeline'
|
|
120
120
|
Requires-Dist: unstructured[local-inference] ; extra == 'pipeline'
|
|
121
121
|
Provides-Extra: tools
|
|
122
|
+
Requires-Dist: openapi-spec-validator ; extra == 'tools'
|
|
122
123
|
Requires-Dist: playwright ; extra == 'tools'
|
|
123
124
|
|
|
124
125
|
## Introduction
|
|
@@ -2,10 +2,10 @@ sunholo/__init__.py,sha256=0CdpufyRKWyZe7J7UKigL6j_qOorM-p0OjHIAuf9M38,864
|
|
|
2
2
|
sunholo/logging.py,sha256=YfIN1oP3dOEkkYkyRBU8BGS3uJFGwUDsFCl8mIVbwvE,12225
|
|
3
3
|
sunholo/agents/__init__.py,sha256=Hb4NXy2rN-83Z0-UDRwX-LXv2R29lcbSFPf8G6q4fZg,380
|
|
4
4
|
sunholo/agents/chat_history.py,sha256=8iX1bgvRW6fdp6r_DQR_caPHYrZ_9QJJgPxCiSDf3q8,5380
|
|
5
|
-
sunholo/agents/dispatch_to_qa.py,sha256=
|
|
6
|
-
sunholo/agents/langserve.py,sha256=
|
|
5
|
+
sunholo/agents/dispatch_to_qa.py,sha256=A8skiZ-CtDvYdP0tnXL4sWM3BCDBgdjFVyrqy-h8Aa4,8374
|
|
6
|
+
sunholo/agents/langserve.py,sha256=eSNJ4G5eGKjmyMQLM_uTOjiS-D_W4QhCLrsC4Vsnk7E,4407
|
|
7
7
|
sunholo/agents/pubsub.py,sha256=5hbbhbBGyVWRpt2sAGC5FEheYH1mCCwVUhZEB1S7vGg,1337
|
|
8
|
-
sunholo/agents/route.py,sha256=
|
|
8
|
+
sunholo/agents/route.py,sha256=YL9a99X1vwSWH8XWo3En1UryxhBFEFhjkbNN1X_YDHg,2905
|
|
9
9
|
sunholo/agents/special_commands.py,sha256=ecD5jrBVXo170sdgPILi0m_m_4nRFEv6qKn5zYEvEK8,6494
|
|
10
10
|
sunholo/agents/swagger.py,sha256=wK90aGOgUojZjfMcjqhhJ_ksJ6ZCsVT1Iy02oU6Q5XM,10786
|
|
11
11
|
sunholo/agents/fastapi/__init__.py,sha256=S_pj4_bTUmDGoq_exaREHlOKThi0zTuGT0VZY0YfODQ,88
|
|
@@ -33,19 +33,19 @@ sunholo/chunker/pdfs.py,sha256=daCZ1xjn1YvxlifIyxskWNpLJLe-Q9D_Jq12MWx3tZo,2473
|
|
|
33
33
|
sunholo/chunker/publish.py,sha256=tiO615A2uo_ZjzdFDzNH1PL_1kJeLMUQwLJ4w67rNIc,2932
|
|
34
34
|
sunholo/chunker/splitter.py,sha256=jtGfi_ZdhVdyFhfw0e4ynEpmwIyrxQtV63OituYWy6o,6729
|
|
35
35
|
sunholo/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
-
sunholo/cli/chat_vac.py,sha256=
|
|
37
|
-
sunholo/cli/cli.py,sha256=
|
|
36
|
+
sunholo/cli/chat_vac.py,sha256=nDhBwUW7RHj7s4qhUcSK2FK4ae031iM71eKQ_WLBxgc,18695
|
|
37
|
+
sunholo/cli/cli.py,sha256=u70fcSQzQx2iPvE23SVCVYRFabmZ-XtgEd6vHcrABi0,3725
|
|
38
38
|
sunholo/cli/cli_init.py,sha256=JMZ9AX2cPDZ-_mv3adiv2ToFVNyRPtjk9Biszl1kiR0,2358
|
|
39
39
|
sunholo/cli/configs.py,sha256=QUM9DvKOdZmEQRM5uI3Nh887T0YDiSMr7O240zTLqws,4546
|
|
40
40
|
sunholo/cli/deploy.py,sha256=zxdwUsRTRMC8U5vyRv0JiKBLFn84Ug_Tc88-_h9hJSs,1609
|
|
41
|
-
sunholo/cli/embedder.py,sha256=
|
|
41
|
+
sunholo/cli/embedder.py,sha256=NAiJy6DmIB3x8wY3ZZ2qHdTubjrwk603eiofWfakfCk,7311
|
|
42
42
|
sunholo/cli/merge_texts.py,sha256=U9vdMwKmcPoc6iPOWX5MKSxn49dNGbNzVLw8ui5PhEU,1823
|
|
43
43
|
sunholo/cli/run_proxy.py,sha256=OeR12ZfnasbJ-smBZQznmGufoDa4iNjUN9FCFo5JxSc,11520
|
|
44
44
|
sunholo/cli/sun_rich.py,sha256=UpMqeJ0C8i0pkue1AHnnyyX0bFJ9zZeJ7HBR6yhuA8A,54
|
|
45
45
|
sunholo/cli/swagger.py,sha256=absYKAU-7Yd2eiVNUY-g_WLl2zJfeRUNdWQ0oH8M_HM,1564
|
|
46
46
|
sunholo/components/__init__.py,sha256=IDoylb74zFKo6NIS3RQqUl0PDFBGVxM1dfUmO7OJ44U,176
|
|
47
47
|
sunholo/components/llm.py,sha256=T4we3tGmqUj4tPwxQr9M6AXv_BALqZV_dRSvINan-oU,10374
|
|
48
|
-
sunholo/components/retriever.py,sha256=
|
|
48
|
+
sunholo/components/retriever.py,sha256=BFUw_6turT3CQJZWv_uXylmH5fHdb0gKfKJrQ_j6MGY,6533
|
|
49
49
|
sunholo/components/vectorstore.py,sha256=zUJ90L1S4IyxLB0JUWopeuwVjcsSqdhj1QreEfsJhsE,5548
|
|
50
50
|
sunholo/database/__init__.py,sha256=Zz0Shcq-CtStf9rJGIYB_Ybzb8rY_Q9mfSj-nviM490,241
|
|
51
51
|
sunholo/database/alloydb.py,sha256=d9W0pbZB0jTVIGF5OVaQ6kXHo-X3-6e9NpWNmV5e9UY,10464
|
|
@@ -67,16 +67,18 @@ sunholo/discovery_engine/discovery_engine_client.py,sha256=YYsFeaW41l8jmWCruQnYx
|
|
|
67
67
|
sunholo/embedder/__init__.py,sha256=sI4N_CqgEVcrMDxXgxKp1FsfsB4FpjoXgPGkl4N_u4I,44
|
|
68
68
|
sunholo/embedder/embed_chunk.py,sha256=d_dIzeNF630Q0Ar-u1hxos60s0tLIImJccAvuo_LTIw,6814
|
|
69
69
|
sunholo/gcs/__init__.py,sha256=SZvbsMFDko40sIRHTHppA37IijvJTae54vrhooEF5-4,90
|
|
70
|
-
sunholo/gcs/add_file.py,sha256=
|
|
70
|
+
sunholo/gcs/add_file.py,sha256=vWRjxuHBQkrPNrr9tRSFGT0N_nVIw120mqDEHiaHwuQ,7115
|
|
71
71
|
sunholo/gcs/download_url.py,sha256=Kg9EdPnc---YSUTAZEdzJeITjDtQSLMYwb4uiU9LhIQ,6440
|
|
72
72
|
sunholo/gcs/metadata.py,sha256=C9sMPsHsq1ETetdQCqB3EBs3Kws8b8QHS9L7ei_v5aw,891
|
|
73
|
+
sunholo/invoke/__init__.py,sha256=Dxivd9cU92X4v2JAZet4f7L2RJ5l_30rt9t2NiD-iLA,55
|
|
74
|
+
sunholo/invoke/invoke_vac_utils.py,sha256=0JkCZDBEkRImzuB-nf70dF75t0WKtgA9G4TdaQJUB08,5240
|
|
73
75
|
sunholo/langfuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
76
|
sunholo/langfuse/callback.py,sha256=CTaos8sYcrga949BG6lIZ4I62DiiQSHxwz5re9XjDWQ,1677
|
|
75
|
-
sunholo/langfuse/prompts.py,sha256=
|
|
77
|
+
sunholo/langfuse/prompts.py,sha256=EkbzSw9Jr05ULMsRDoGOp-frbtCZpnvdYSJEYNpzfX8,1293
|
|
76
78
|
sunholo/llamaindex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
79
|
sunholo/llamaindex/generate.py,sha256=l1Picr-hVwkmAUD7XmTCa63qY9ERliFHQXwyX3BqB2Q,686
|
|
78
80
|
sunholo/llamaindex/get_files.py,sha256=6rhXCDqQ_lrIapISQ_OYQDjiSATXvS_9m3qq53-oIl0,781
|
|
79
|
-
sunholo/llamaindex/import_files.py,sha256=
|
|
81
|
+
sunholo/llamaindex/import_files.py,sha256=Iy_wkZCUSyrue_tAEHgnYaKDgg3-5GVygokHn3kd134,5747
|
|
80
82
|
sunholo/lookup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
83
|
sunholo/lookup/model_lookup.yaml,sha256=O7o-jP53MLA06C8pI-ILwERShO-xf6z_258wtpZBv6A,739
|
|
82
84
|
sunholo/patches/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -91,17 +93,18 @@ sunholo/qna/parsers.py,sha256=Wn2X47_yeE39oeqxxgDr7jgBT-N1anYpJtVBq-623O4,2146
|
|
|
91
93
|
sunholo/qna/retry.py,sha256=gFgOf9AxrZMIO9OwOYu1EW7rhNhyfnw_o4XAsNLBOVQ,2021
|
|
92
94
|
sunholo/streaming/__init__.py,sha256=MpbydI2UYo_adttPQFkxNM33b-QRyNEbrKJx0C2AGPc,241
|
|
93
95
|
sunholo/streaming/content_buffer.py,sha256=fWcg0oTf470M3U40VAChfmHmWRFgRD8VaT90jNfBCH0,6455
|
|
94
|
-
sunholo/streaming/langserve.py,sha256=
|
|
96
|
+
sunholo/streaming/langserve.py,sha256=Etbbo9crq4kXurgQtfG4p1yj_MwU5_KCYDINHS-tJl0,6507
|
|
95
97
|
sunholo/streaming/stream_lookup.py,sha256=uTTUjf96mV7OCc-Sc8N09Fpu5g0T_mD_HbSzivtHMFQ,353
|
|
96
98
|
sunholo/streaming/streaming.py,sha256=9z6pXINEopuL_Z1RnmgXAoZJum9dzyuOxqYtEYnjf8w,16405
|
|
97
99
|
sunholo/summarise/__init__.py,sha256=MZk3dblUMODcPb1crq4v-Z508NrFIpkSWNf9FIO8BcU,38
|
|
98
100
|
sunholo/summarise/summarise.py,sha256=C3HhjepTjUhUC8FLk4jMQIBvq1BcORniwuTFHjPVhVo,3784
|
|
99
101
|
sunholo/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
100
102
|
sunholo/tools/web_browser.py,sha256=NgsAeVcndl-vMAbAfIzDJ8eRfCh5LDZan16OCNEKFmI,7094
|
|
101
|
-
sunholo/utils/__init__.py,sha256=
|
|
103
|
+
sunholo/utils/__init__.py,sha256=Hv02T5L2zYWvCso5hzzwm8FQogwBq0OgtUbN_7Quzqc,89
|
|
102
104
|
sunholo/utils/api_key.py,sha256=Ct4bIAQZxzPEw14hP586LpVxBAVi_W9Serpy0BK-7KI,244
|
|
103
105
|
sunholo/utils/big_context.py,sha256=gJIP7_ZL-YSLhOMq8jmFTMqH1wq8eB1NK7oKPeZAq2s,5578
|
|
104
|
-
sunholo/utils/config.py,sha256=
|
|
106
|
+
sunholo/utils/config.py,sha256=Ute6SORPtkMnZy-BVVv0rtN28qSQ77GAzb7XtZGIAT0,8901
|
|
107
|
+
sunholo/utils/config_class.py,sha256=uyAsPXdxOY47CbQ8RifhUDL2BlxWP2QI-DIWBNlv6yk,8421
|
|
105
108
|
sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
|
|
106
109
|
sunholo/utils/gcp.py,sha256=uueODEpA-P6O15-t0hmcGC9dONLO_hLfzSsSoQnkUss,4854
|
|
107
110
|
sunholo/utils/gcp_project.py,sha256=0ozs6tzI4qEvEeXb8MxLnCdEVoWKxlM6OH05htj7_tc,1325
|
|
@@ -110,14 +113,13 @@ sunholo/utils/timedelta.py,sha256=BbLabEx7_rbErj_YbNM0MBcaFN76DC4PTe4zD2ucezg,49
|
|
|
110
113
|
sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
|
|
111
114
|
sunholo/utils/version.py,sha256=P1QAJQdZfT2cMqdTSmXmcxrD2PssMPEGM-WI6083Fck,237
|
|
112
115
|
sunholo/vertex/__init__.py,sha256=XH7FUKxdIgN9H2iDcWxL3sRnVHC3297G24RqEn4Ob0Y,240
|
|
113
|
-
sunholo/vertex/
|
|
114
|
-
sunholo/vertex/extensions_class.py,sha256=E0ix4YqFQG9EglKeTmp2-zwuZUA2crileGahAhe4g5k,12164
|
|
116
|
+
sunholo/vertex/extensions_class.py,sha256=4PsUM9dSYrIPpq9bZ3K2rL9MRb_rlqAgnMsW0o9gHck,15855
|
|
115
117
|
sunholo/vertex/init.py,sha256=-w7b9GKsyJnAJpYHYz6_zBUtmeJeLXlEkgOfwoe4DEI,2715
|
|
116
|
-
sunholo/vertex/memory_tools.py,sha256=
|
|
118
|
+
sunholo/vertex/memory_tools.py,sha256=pomHrDKqvY8MZxfUqoEwhdlpCvSGP6KmFJMVKOimXjs,6842
|
|
117
119
|
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.
|
|
120
|
+
sunholo-0.73.2.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
121
|
+
sunholo-0.73.2.dist-info/METADATA,sha256=TUj-qcbRdSqJj0mt0Nz3mhoiz2oYwRgWEfVt3vDqgag,6909
|
|
122
|
+
sunholo-0.73.2.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
123
|
+
sunholo-0.73.2.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
124
|
+
sunholo-0.73.2.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
125
|
+
sunholo-0.73.2.dist-info/RECORD,,
|