sunholo 0.92.2__py3-none-any.whl → 0.92.3__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/flask/vac_routes.py +12 -11
- sunholo/genai/process_funcs_cls.py +56 -24
- sunholo/utils/config_class.py +1 -0
- {sunholo-0.92.2.dist-info → sunholo-0.92.3.dist-info}/METADATA +2 -2
- {sunholo-0.92.2.dist-info → sunholo-0.92.3.dist-info}/RECORD +9 -9
- {sunholo-0.92.2.dist-info → sunholo-0.92.3.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.92.2.dist-info → sunholo-0.92.3.dist-info}/WHEEL +0 -0
- {sunholo-0.92.2.dist-info → sunholo-0.92.3.dist-info}/entry_points.txt +0 -0
- {sunholo-0.92.2.dist-info → sunholo-0.92.3.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ from ...qna.parsers import parse_output
|
|
|
9
9
|
from ...streaming import start_streaming_chat
|
|
10
10
|
from ...archive import archive_qa
|
|
11
11
|
from ...custom_logging import log
|
|
12
|
-
from ...utils
|
|
12
|
+
from ...utils import ConfigManager
|
|
13
13
|
from ...utils.version import sunholo_version
|
|
14
14
|
import os
|
|
15
15
|
from ...gcs.add_file import add_file_to_gcs, handle_base64_image
|
|
@@ -178,7 +178,7 @@ if __name__ == "__main__":
|
|
|
178
178
|
if span:
|
|
179
179
|
generation = span.generation(
|
|
180
180
|
name="start_streaming_chat",
|
|
181
|
-
metadata=vac_config,
|
|
181
|
+
metadata=vac_config.configs_by_kind,
|
|
182
182
|
input = all_input,
|
|
183
183
|
completion_start_time=str(int(datetime.datetime.now().timestamp())),
|
|
184
184
|
model=vac_config.get("model") or vac_config.get("llm")
|
|
@@ -264,7 +264,7 @@ if __name__ == "__main__":
|
|
|
264
264
|
trace = prep["trace"]
|
|
265
265
|
span = prep["span"]
|
|
266
266
|
command_response = prep["command_response"]
|
|
267
|
-
vac_config = prep["vac_config"]
|
|
267
|
+
vac_config: ConfigManager = prep["vac_config"]
|
|
268
268
|
all_input = prep["all_input"]
|
|
269
269
|
|
|
270
270
|
if command_response:
|
|
@@ -274,9 +274,9 @@ if __name__ == "__main__":
|
|
|
274
274
|
if span:
|
|
275
275
|
generation = span.generation(
|
|
276
276
|
name="vac_interpreter",
|
|
277
|
-
metadata=vac_config,
|
|
277
|
+
metadata=vac_config.configs_by_kind,
|
|
278
278
|
input = all_input,
|
|
279
|
-
model=vac_config.
|
|
279
|
+
model=vac_config.vacConfig("model") or vac_config.vacConfig("llm")
|
|
280
280
|
)
|
|
281
281
|
bot_output = observed_vac_interpreter(
|
|
282
282
|
question=all_input["user_input"],
|
|
@@ -534,13 +534,14 @@ if __name__ == "__main__":
|
|
|
534
534
|
trace = self.create_langfuse_trace(request, vector_name, trace_id)
|
|
535
535
|
log.info(f"Using existing langfuse trace: {trace_id}")
|
|
536
536
|
|
|
537
|
-
config, _ = load_config("config/llm_config.yaml")
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
537
|
+
#config, _ = load_config("config/llm_config.yaml")
|
|
538
|
+
try:
|
|
539
|
+
vac_config = ConfigManager(vector_name)
|
|
540
|
+
except Exception as e:
|
|
541
|
+
raise ValueError(f"Unable to find vac_config for {vector_name} - {str(e)}")
|
|
541
542
|
|
|
542
543
|
if trace:
|
|
543
|
-
trace.update(input=data, metadata=vac_config)
|
|
544
|
+
trace.update(input=data, metadata=vac_config.configs_by_kind)
|
|
544
545
|
|
|
545
546
|
user_input = data.pop('user_input').strip()
|
|
546
547
|
stream_wait_time = data.pop('stream_wait_time', 7)
|
|
@@ -563,7 +564,7 @@ if __name__ == "__main__":
|
|
|
563
564
|
if trace:
|
|
564
565
|
span = trace.span(
|
|
565
566
|
name="VAC",
|
|
566
|
-
metadata=vac_config,
|
|
567
|
+
metadata=vac_config.configs_by_kind,
|
|
567
568
|
input = all_input
|
|
568
569
|
)
|
|
569
570
|
command_response = handle_special_commands(user_input, vector_name, paired_messages)
|
|
@@ -10,6 +10,7 @@ import json
|
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
12
|
import google.generativeai as genai
|
|
13
|
+
import proto
|
|
13
14
|
except ImportError:
|
|
14
15
|
genai = None
|
|
15
16
|
|
|
@@ -75,6 +76,8 @@ class GenAIFunctionProcessor:
|
|
|
75
76
|
|
|
76
77
|
This method should be overridden in subclasses to provide the specific
|
|
77
78
|
function implementations required for the application.
|
|
79
|
+
|
|
80
|
+
Note: All functions need arguments to avoid errors.
|
|
78
81
|
|
|
79
82
|
Returns:
|
|
80
83
|
dict: A dictionary where keys are function names and values are function objects
|
|
@@ -160,17 +163,24 @@ class GenAIFunctionProcessor:
|
|
|
160
163
|
result = part[2]
|
|
161
164
|
|
|
162
165
|
if func_name == function_name:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
# Try to decode the result if it's a string
|
|
167
|
+
if isinstance(result, str):
|
|
168
|
+
try:
|
|
169
|
+
result = json.loads(result)
|
|
170
|
+
except json.JSONDecodeError:
|
|
171
|
+
log.warning(f"Failed to decode JSON result for function {function_name}: {result}")
|
|
172
|
+
continue # Skip this result if decoding fails
|
|
173
|
+
|
|
174
|
+
normalized_target_value = {k: v for k, v in target_value.items()} if isinstance(target_value, dict) else target_value
|
|
175
|
+
log.info(f"{normalized_target_value=} {result=}")
|
|
176
|
+
|
|
177
|
+
if isinstance(result, dict) and isinstance(normalized_target_value, dict):
|
|
178
|
+
for key, expected_value in normalized_target_value.items():
|
|
179
|
+
if key in result and result[key] == expected_value:
|
|
180
|
+
log.info(f"The key '{key}' has the expected value in both dictionaries.")
|
|
181
|
+
return True
|
|
172
182
|
return False
|
|
173
|
-
elif result ==
|
|
183
|
+
elif result == normalized_target_value:
|
|
174
184
|
log.info(f"Target value '{target_value}' found in the result of function '{function_name}'.")
|
|
175
185
|
return True
|
|
176
186
|
|
|
@@ -227,16 +237,30 @@ class GenAIFunctionProcessor:
|
|
|
227
237
|
if fn := part.function_call:
|
|
228
238
|
# Extract parameters for the function call
|
|
229
239
|
function_name = fn.name
|
|
230
|
-
|
|
240
|
+
|
|
241
|
+
# Handle empty parameters
|
|
242
|
+
if fn.args is None or not fn.args:
|
|
243
|
+
params_obj = {}
|
|
244
|
+
else:
|
|
245
|
+
params_obj = {key: val for key, val in fn.args.items()}
|
|
246
|
+
|
|
231
247
|
params = ', '.join(f'{key}={val}' for key, val in params_obj.items())
|
|
232
248
|
log.info(f"Executing {function_name} with params {params}")
|
|
233
249
|
|
|
234
250
|
# Check if the function is in our dictionary of available functions
|
|
235
251
|
if function_name in self.funcs:
|
|
252
|
+
fn_exec = self.funcs[function_name]
|
|
236
253
|
try:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
254
|
+
if not isinstance(fn_exec, genai.protos.FunctionDeclaration):
|
|
255
|
+
# Execute the function with the provided parameters
|
|
256
|
+
result = fn_exec(**params_obj)
|
|
257
|
+
log.info(f"Got result from {function_name}: {result}")
|
|
258
|
+
else:
|
|
259
|
+
fn_result = type(fn).to_dict(fn)
|
|
260
|
+
result = fn_result.get("result")
|
|
261
|
+
if not result:
|
|
262
|
+
log.warning("No result found for {function_name}")
|
|
263
|
+
log.info(f"No execution of {function_name} as a FunctionDeclatation object, just returning args {result}")
|
|
240
264
|
except Exception as err:
|
|
241
265
|
error_message = f"Error in {function_name}: {str(err)}"
|
|
242
266
|
traceback_details = traceback.format_exc()
|
|
@@ -350,13 +374,13 @@ class GenAIFunctionProcessor:
|
|
|
350
374
|
while guardrail < guardrail_max:
|
|
351
375
|
|
|
352
376
|
callback.on_llm_new_token(
|
|
353
|
-
token=f"\n----Loop [{guardrail}] Start------\nFunctions
|
|
377
|
+
token=f"\n----Loop [{guardrail}] Start------\nFunctions: {list(self.funcs.keys())}\n"
|
|
354
378
|
)
|
|
355
379
|
|
|
356
380
|
content_parse = ""
|
|
357
381
|
for i, chunk in enumerate(content):
|
|
358
382
|
content_parse += f"\n - {i}) {chunk}"
|
|
359
|
-
|
|
383
|
+
content_parse += f"\n== End input content for loop [{guardrail}] =="
|
|
360
384
|
|
|
361
385
|
log.info(f"== Start input content for loop [{guardrail}]\n ## Content: {content_parse}")
|
|
362
386
|
this_text = "" # reset for this loop
|
|
@@ -367,7 +391,7 @@ class GenAIFunctionProcessor:
|
|
|
367
391
|
response = chat.send_message(content, stream=True)
|
|
368
392
|
|
|
369
393
|
except Exception as e:
|
|
370
|
-
msg = f"Error sending {content} to model: {str(e)}"
|
|
394
|
+
msg = f"Error sending {content} to model: {str(e)} - {traceback.format_exc()}"
|
|
371
395
|
log.info(msg)
|
|
372
396
|
callback.on_llm_new_token(token=msg)
|
|
373
397
|
break
|
|
@@ -421,6 +445,9 @@ class GenAIFunctionProcessor:
|
|
|
421
445
|
callback.on_llm_new_token(token=f"\n--- function calling: {fn_log} ...\n")
|
|
422
446
|
|
|
423
447
|
try:
|
|
448
|
+
# Convert MapComposite to a standard Python dictionary
|
|
449
|
+
if isinstance(fn_result, proto.marshal.collections.maps.MapComposite):
|
|
450
|
+
fn_result = dict(fn_result)
|
|
424
451
|
fn_result_json = json.loads(fn_result)
|
|
425
452
|
if not isinstance(fn_result_json, dict):
|
|
426
453
|
log.warning(f"{fn_result} was loaded but is not a dictionary")
|
|
@@ -433,9 +460,15 @@ class GenAIFunctionProcessor:
|
|
|
433
460
|
fn_result_json = None
|
|
434
461
|
|
|
435
462
|
if fn == "decide_to_go_on":
|
|
436
|
-
|
|
463
|
+
log.info(f"{fn_result_json} {fn_result=} {type(fn_result)}")
|
|
464
|
+
go_on_args = fn_result_json
|
|
465
|
+
if go_on_args:
|
|
466
|
+
token = f"\n\n{'STOPPING' if not go_on_args.get('go_on') else 'CONTINUE'}: {go_on_args.get('chat_summary')}"
|
|
467
|
+
else:
|
|
468
|
+
log.warning(f"{fn_result_json} did not work for decide_to_go_on")
|
|
469
|
+
token = f"Error calling decide_to_go_on with {fn_result_json}\n"
|
|
437
470
|
else:
|
|
438
|
-
token = f"---
|
|
471
|
+
token = f"--- {fn} call result: \n"
|
|
439
472
|
if fn_result_json:
|
|
440
473
|
if fn_result_json.get('stdout'):
|
|
441
474
|
text = fn_result_json.get('stdout').encode('utf-8').decode('unicode_escape')
|
|
@@ -444,9 +477,9 @@ class GenAIFunctionProcessor:
|
|
|
444
477
|
text = fn_result_json.get('stdout').encode('utf-8').decode('unicode_escape')
|
|
445
478
|
token += text
|
|
446
479
|
if not fn_result_json.get('stdout') and fn_result_json.get('stderr'):
|
|
447
|
-
token += f"
|
|
480
|
+
token += f"{fn_result}\n"
|
|
448
481
|
else:
|
|
449
|
-
token += f"
|
|
482
|
+
token += f"{fn_result}\n--- {fn} result end ---\n"
|
|
450
483
|
|
|
451
484
|
big_text += token
|
|
452
485
|
this_text += token
|
|
@@ -479,11 +512,10 @@ class GenAIFunctionProcessor:
|
|
|
479
512
|
break
|
|
480
513
|
|
|
481
514
|
usage_metadata["functions_called"] = functions_called
|
|
482
|
-
usage_metadata["function_results"] = function_results
|
|
515
|
+
#usage_metadata["function_results"] = function_results
|
|
483
516
|
|
|
484
517
|
return big_text, usage_metadata
|
|
485
518
|
|
|
486
|
-
# needs to be static to avoid bound methods in function call
|
|
487
519
|
@staticmethod
|
|
488
520
|
def decide_to_go_on(go_on: bool, chat_summary: str) -> dict:
|
|
489
521
|
"""
|
|
@@ -503,4 +535,4 @@ class GenAIFunctionProcessor:
|
|
|
503
535
|
Returns:
|
|
504
536
|
boolean: True to carry on, False to continue
|
|
505
537
|
"""
|
|
506
|
-
return {"go_on": go_on, "chat_summary": chat_summary}
|
|
538
|
+
return json.dumps({"go_on": go_on, "chat_summary": chat_summary})
|
sunholo/utils/config_class.py
CHANGED
|
@@ -26,6 +26,7 @@ class ConfigManager:
|
|
|
26
26
|
agent = config.vacConfig("agent")
|
|
27
27
|
```
|
|
28
28
|
"""
|
|
29
|
+
print(f"Current working directory: {os.getcwd()}")
|
|
29
30
|
if os.getenv("VAC_CONFIG_FOLDER") is None:
|
|
30
31
|
print("WARNING: No VAC_CONFIG_FOLDER environment variable was specified")
|
|
31
32
|
local_config_folder = os.path.join(os.getcwd(), "config")
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.92.
|
|
3
|
+
Version: 0.92.3
|
|
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.92.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.92.3.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -14,7 +14,7 @@ sunholo/agents/fastapi/qna_routes.py,sha256=lKHkXPmwltu9EH3RMwmD153-J6pE7kWQ4BhB
|
|
|
14
14
|
sunholo/agents/flask/__init__.py,sha256=poJDKMr2qj8qMb99JqCvCPSiEt1tj2tLQ3hKW3f2aVw,107
|
|
15
15
|
sunholo/agents/flask/base.py,sha256=FgSaCODyoTtlstJtsqlLPScdgRUtv9_plxftdzHdVFo,809
|
|
16
16
|
sunholo/agents/flask/qna_routes.py,sha256=uwUD1yrzOPH27m2AXpiQrPk_2VfJOQOM6dAynOWQtoQ,22532
|
|
17
|
-
sunholo/agents/flask/vac_routes.py,sha256=
|
|
17
|
+
sunholo/agents/flask/vac_routes.py,sha256=k8OhIYHSAjhzKHHvwExbNJYBa0hswJh23pB2BZgs37w,23330
|
|
18
18
|
sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
|
|
19
19
|
sunholo/archive/archive.py,sha256=PxVfDtO2_2ZEEbnhXSCbXLdeoHoQVImo4y3Jr2XkCFY,1204
|
|
20
20
|
sunholo/auth/__init__.py,sha256=TeP-OY0XGxYV_8AQcVGoh35bvyWhNUcMRfhuD5l44Sk,91
|
|
@@ -86,7 +86,7 @@ sunholo/gcs/download_url.py,sha256=q1NiJSvEhdNrmU5ZJ-sBCMC_J5CxzrajY8LRgdPOV_M,6
|
|
|
86
86
|
sunholo/gcs/metadata.py,sha256=oQLcXi4brsZ74aegWyC1JZmhlaEV270HS5_UWtAYYWE,898
|
|
87
87
|
sunholo/genai/__init__.py,sha256=dBl6IA3-Fx6-Vx81r0XqxHlUq6WeW1iDX188dpChu8s,115
|
|
88
88
|
sunholo/genai/init.py,sha256=yG8E67TduFCTQPELo83OJuWfjwTnGZsyACospahyEaY,687
|
|
89
|
-
sunholo/genai/process_funcs_cls.py,sha256=
|
|
89
|
+
sunholo/genai/process_funcs_cls.py,sha256=u4eOU31IaIybia7i40LfwezwcWJbADlAn3qIvio802Y,23789
|
|
90
90
|
sunholo/genai/safety.py,sha256=mkFDO_BeEgiKjQd9o2I4UxB6XI7a9U-oOFjZ8LGRUC4,1238
|
|
91
91
|
sunholo/invoke/__init__.py,sha256=bELcqIjzKvaupcIN5OQmDgGx_8jARtH9T6PCe8UgcvE,99
|
|
92
92
|
sunholo/invoke/async_class.py,sha256=vmLT6DqE1YaPd4W88_QzPQvSzsjwLUAwt23vGZm-BEs,5767
|
|
@@ -128,7 +128,7 @@ sunholo/utils/__init__.py,sha256=Hv02T5L2zYWvCso5hzzwm8FQogwBq0OgtUbN_7Quzqc,89
|
|
|
128
128
|
sunholo/utils/api_key.py,sha256=Ct4bIAQZxzPEw14hP586LpVxBAVi_W9Serpy0BK-7KI,244
|
|
129
129
|
sunholo/utils/big_context.py,sha256=gJIP7_ZL-YSLhOMq8jmFTMqH1wq8eB1NK7oKPeZAq2s,5578
|
|
130
130
|
sunholo/utils/config.py,sha256=aG29MXcL5qzQMtCMqcdy-2ysDCYf9Zn_ZLk5NNOQNSE,8982
|
|
131
|
-
sunholo/utils/config_class.py,sha256=
|
|
131
|
+
sunholo/utils/config_class.py,sha256=D8lrqubVcUkHQLjfMxYOgqdwAoAJB8gcv7knVqgCzAo,10015
|
|
132
132
|
sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
|
|
133
133
|
sunholo/utils/gcp.py,sha256=uueODEpA-P6O15-t0hmcGC9dONLO_hLfzSsSoQnkUss,4854
|
|
134
134
|
sunholo/utils/gcp_project.py,sha256=Fa0IhCX12bZ1ctF_PKN8PNYd7hihEUfb90kilBfUDjg,1411
|
|
@@ -144,9 +144,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
|
|
|
144
144
|
sunholo/vertex/memory_tools.py,sha256=q_phxgGX2TG2j2MXNULF2xGzQnQPENwjPN9nZ_A9Gh0,7526
|
|
145
145
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
|
146
146
|
sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
|
|
147
|
-
sunholo-0.92.
|
|
148
|
-
sunholo-0.92.
|
|
149
|
-
sunholo-0.92.
|
|
150
|
-
sunholo-0.92.
|
|
151
|
-
sunholo-0.92.
|
|
152
|
-
sunholo-0.92.
|
|
147
|
+
sunholo-0.92.3.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
148
|
+
sunholo-0.92.3.dist-info/METADATA,sha256=9KgmjEFrRDyKC7327JHXu0vgz01K1zOa0y7Tr_DVvwA,7806
|
|
149
|
+
sunholo-0.92.3.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
150
|
+
sunholo-0.92.3.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
151
|
+
sunholo-0.92.3.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
152
|
+
sunholo-0.92.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|