sunholo 0.71.15__py3-none-any.whl → 0.71.16__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.
@@ -15,7 +15,6 @@
15
15
 
16
16
  import json
17
17
  import traceback
18
- import datetime
19
18
  import uuid
20
19
 
21
20
  from ...agents import extract_chat_history, handle_special_commands
@@ -142,7 +141,7 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
142
141
  name="start_streaming_chat",
143
142
  metadata=vac_config,
144
143
  input = all_input,
145
- completion_start_time=datetime.datetime.now(),
144
+ completion_start_time=datetime.now(),
146
145
  model=vac_config.get("model") or vac_config.get("llm")
147
146
  )
148
147
 
sunholo/gcs/add_file.py CHANGED
@@ -25,25 +25,63 @@ from ..logging import log
25
25
  from ..utils.config import load_config_key
26
26
 
27
27
 
28
- def handle_base64_image(base64_data, vector_name):
28
+ def handle_base64_image(base64_data: str, vector_name: str, extension: str):
29
+ """
30
+ Handle base64 image data, decode it, save it as a file, upload it to GCS, and return the image URI and MIME type.
31
+
32
+ Args:
33
+ base64_data (str): The base64 encoded image data.
34
+ vector_name (str): The vector name for the GCS path.
35
+ extension (str): The file extension of the image (e.g., ".jpg", ".png").
36
+
37
+ Returns:
38
+ Tuple[str, str]: The URI of the uploaded image and the MIME type.
39
+ """
29
40
  model = load_config_key("llm", vector_name, "vacConfig")
30
- if model.startswith("openai"): # pass it to gpt directly
31
- return base64_data, base64_data.split(",",1)
32
-
41
+ if model.startswith("openai"): # pass it to gpt directly
42
+ return base64_data, base64_data.split(",", 1)
43
+
33
44
  try:
34
45
  header, encoded = base64_data.split(",", 1)
35
46
  data = base64.b64decode(encoded)
36
47
 
37
- filename = f"{uuid.uuid4()}.jpg"
48
+ filename = f"{uuid.uuid4()}{extension}"
38
49
  with open(filename, "wb") as f:
39
50
  f.write(data)
40
51
 
41
52
  image_uri = add_file_to_gcs(filename, vector_name)
42
53
  os.remove(filename) # Clean up the saved file
43
- return image_uri, "image/jpeg"
54
+
55
+ # Determine MIME type based on extension
56
+ mime_type = {
57
+ ".jpg": "image/jpeg",
58
+ ".jpeg": "image/jpeg",
59
+ ".png": "image/png",
60
+ ".gif": "image/gif",
61
+ ".bmp": "image/bmp",
62
+ ".tiff": "image/tiff"
63
+ }.get(extension.lower(), "application/octet-stream") # Default MIME type if unknown
64
+
65
+ return image_uri, mime_type
44
66
  except Exception as e:
45
67
  raise Exception(f'Base64 image upload failed: {str(e)}')
46
68
 
69
+
70
+ def resolve_bucket(vector_name):
71
+ bucket_config = load_config_key("upload", vector_name, "vacConfig")
72
+ if bucket_config:
73
+ if bucket_config.get("buckets"):
74
+ bucket_name = bucket_config.get("buckets").get("all")
75
+
76
+ bucket_name = bucket_name if bucket_name else os.getenv('GCS_BUCKET', None)
77
+ if bucket_name is None:
78
+ raise ValueError("No bucket found to upload to: GCS_BUCKET returned None")
79
+
80
+ if bucket_name.startswith("gs://"):
81
+ bucket_name = bucket_name.removeprefix("gs://")
82
+
83
+ return bucket_name
84
+
47
85
  def add_file_to_gcs(filename: str, vector_name:str, bucket_name: str=None, metadata:dict=None, bucket_filepath:str=None):
48
86
 
49
87
  if not storage:
@@ -56,17 +94,7 @@ def add_file_to_gcs(filename: str, vector_name:str, bucket_name: str=None, metad
56
94
  return None
57
95
 
58
96
  if bucket_name is None:
59
- bucket_config = load_config_key("upload", vector_name, "vacConfig")
60
- if bucket_config:
61
- if bucket_config.get("buckets"):
62
- bucket_name = bucket_config.get("buckets").get("all")
63
-
64
- bucket_name = bucket_name if bucket_name else os.getenv('GCS_BUCKET', None)
65
- if bucket_name is None:
66
- raise ValueError("No bucket found to upload to: GCS_BUCKET returned None")
67
-
68
- if bucket_name.startswith("gs://"):
69
- bucket_name = bucket_name.removeprefix("gs://")
97
+ bucket_name = resolve_bucket(vector_name)
70
98
 
71
99
  bucket = storage_client.get_bucket(bucket_name)
72
100
  now = datetime.datetime.now()
@@ -136,7 +136,11 @@ class VertexAIExtensions:
136
136
 
137
137
  return response
138
138
 
139
- def execute_code_extension(self, query: str, filenames: list[str] = None, gcs_files: list[str] = None):
139
+ def execute_code_extension(self,
140
+ query: str,
141
+ filenames: list[str] = None,
142
+ gcs_files: list[str] = None,
143
+ bucket_name: str = None):
140
144
  if filenames and gcs_files:
141
145
  raise ValueError("Can't specify both filenames and gcs_files")
142
146
 
@@ -149,7 +153,16 @@ class VertexAIExtensions:
149
153
  break
150
154
 
151
155
  if not code_interpreter_exists:
152
- extension_code_interpreter = extensions.Extension.from_hub("code_interpreter")
156
+ if bucket_name:
157
+ runtime_config = {
158
+ "codeInterpreterRuntimeConfig": {
159
+ "fileInputGcsBucket": f"{bucket_name}/extensions/input/",
160
+ "fileOutputGcsBucket": f"{bucket_name}/extensions/output/",
161
+ }
162
+ }
163
+ extension_code_interpreter = extensions.Extension.from_hub("code_interpreter", runtime_config=runtime_config)
164
+
165
+ # This field is only applicable when `file_output_gcs_bucket` is specified in `Extension.CodeInterpreterRuntimeConfig`.
153
166
 
154
167
  operation_params = {"query": query}
155
168
 
@@ -166,7 +179,7 @@ class VertexAIExtensions:
166
179
 
167
180
  if gcs_files:
168
181
  operation_params["file_gcs_uris"] = gcs_files
169
-
182
+ log.info("Executing code interpreter")
170
183
  response = extension_code_interpreter.execute(
171
184
  operation_id="generate_and_execute",
172
185
  operation_params=operation_params)
@@ -175,7 +188,24 @@ class VertexAIExtensions:
175
188
  [item['name'] for item in response['output_files']])
176
189
 
177
190
  if response.get('execution_error'):
191
+ #TODO: setup iteration many times with a timeout
178
192
  log.error(f"Code Execution Response failed with: {response.get('execution_error')} - maybe retry?")
193
+ new_query = f"""
194
+ <original_query>{query}</original_query>
195
+ <original_output>{response.get('generated_code')}</original_output>
196
+ The code above failed with this error:
197
+ <code_error>{response.get('execution_error')}</code_error>
198
+ Please try again again to satisfy the original query.
199
+ """
200
+ operation_params = {"query": new_query}
201
+ response = extension_code_interpreter.execute(
202
+ operation_id="generate_and_execute",
203
+ operation_params=operation_params)
204
+
205
+ self.CODE_INTERPRETER_WRITTEN_FILES.extend([item['name'] for item in response['output_files']])
206
+ if response.get('execution_error'):
207
+ log.error(f"Code Execution Response failed twice: {response.get('execution_error')}")
208
+
179
209
 
180
210
  return response
181
211
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.71.15
3
+ Version: 0.71.16
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.71.15.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.71.16.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -13,7 +13,7 @@ sunholo/agents/fastapi/base.py,sha256=clk76cHbUAvU0OYJrRfCWX_5f0ACbhDsIzYBhI3wyo
13
13
  sunholo/agents/fastapi/qna_routes.py,sha256=DgK4Btu5XriOC1JaRQ4G_nWEjJfnQ0J5pyLanF6eF1g,3857
14
14
  sunholo/agents/flask/__init__.py,sha256=uqfHNw2Ru3EJ4dJEcbp86h_lkquBQPMxZbjhV_xe3rs,72
15
15
  sunholo/agents/flask/base.py,sha256=FgSaCODyoTtlstJtsqlLPScdgRUtv9_plxftdzHdVFo,809
16
- sunholo/agents/flask/qna_routes.py,sha256=Su8HNcjmEbZ-u7loC2lqWN9Yb9TKbbjrO1Qi-kqLCF8,21839
16
+ sunholo/agents/flask/qna_routes.py,sha256=TUsVn1MGcJ-8JFET5aR9mjGPd4z6K__SjTN8JOOsiTU,21814
17
17
  sunholo/agents/flask/vac_routes.py,sha256=l2-w7x437F0Uu3QvwNueEYPtnKuIee6bHJ7LUMt_tkY,19520
18
18
  sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
19
19
  sunholo/archive/archive.py,sha256=C-UhG5x-XtZ8VheQp92IYJqgD0V3NFQjniqlit94t18,1197
@@ -67,7 +67,7 @@ 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=DtVw_AZwQn-IguR5BJuIi2XJeF_FQXizhJikzRNrXiE,50
70
- sunholo/gcs/add_file.py,sha256=y2s7ZZBiJD3pu1TqRAy0s1SRGvHvzJqSDaYD-MFFh1c,5717
70
+ sunholo/gcs/add_file.py,sha256=K4lvNy22qtFFSJUh6xM7nmJ8_CT-0BIGSNxNXWIt3-U,6643
71
71
  sunholo/gcs/download_url.py,sha256=8XSEf8byfubqs5CMQeF_tn9wxqwUTq3n9mo5mLNIUTA,4801
72
72
  sunholo/gcs/metadata.py,sha256=C9sMPsHsq1ETetdQCqB3EBs3Kws8b8QHS9L7ei_v5aw,891
73
73
  sunholo/langfuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -111,13 +111,13 @@ sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
111
111
  sunholo/utils/version.py,sha256=P1QAJQdZfT2cMqdTSmXmcxrD2PssMPEGM-WI6083Fck,237
112
112
  sunholo/vertex/__init__.py,sha256=XH7FUKxdIgN9H2iDcWxL3sRnVHC3297G24RqEn4Ob0Y,240
113
113
  sunholo/vertex/extensions.py,sha256=d-Ikt9gHFf-jUMPmyU-xHwYe22QtEyr90Ua1LDKgTws,11026
114
- sunholo/vertex/extensions_class.py,sha256=2j4LhvdmzHIMpCI8_7sKy1xYGiHPb7TRnIB2um5-x78,10378
114
+ sunholo/vertex/extensions_class.py,sha256=flvWNxzY_0z_nDuoaXq96mmLCON1At793NpEeaJ6T0E,11893
115
115
  sunholo/vertex/init.py,sha256=-w7b9GKsyJnAJpYHYz6_zBUtmeJeLXlEkgOfwoe4DEI,2715
116
116
  sunholo/vertex/memory_tools.py,sha256=FLTbNX_YbpxxUxZHAsXEihlUgLELfLOfxsdEkwDm_GI,6546
117
117
  sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
118
- sunholo-0.71.15.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
119
- sunholo-0.71.15.dist-info/METADATA,sha256=UQxaV4yVl6XvGIhNI26Sql5JgCLMV8ttsfPEHl-9J6w,6767
120
- sunholo-0.71.15.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
121
- sunholo-0.71.15.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
122
- sunholo-0.71.15.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
123
- sunholo-0.71.15.dist-info/RECORD,,
118
+ sunholo-0.71.16.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
119
+ sunholo-0.71.16.dist-info/METADATA,sha256=xw0dl33vOvPMlNI-Fd_848gY3STZpA7TQZghXh7f0MQ,6767
120
+ sunholo-0.71.16.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
121
+ sunholo-0.71.16.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
122
+ sunholo-0.71.16.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
123
+ sunholo-0.71.16.dist-info/RECORD,,