sunholo 0.92.4__py3-none-any.whl → 0.92.6__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/cli/chat_vac.py CHANGED
@@ -533,6 +533,14 @@ def get_cloud_run_service_url(project, region, service_name):
533
533
  Returns:
534
534
  str: The URL of the Cloud Run service, or an error message if not found.
535
535
  """
536
+ # Try to load existing data from the file, or initialize an empty dict
537
+ file_path = "config/cloud_run_urls.json"
538
+ if os.path.exists(file_path):
539
+ with open(file_path, 'r') as file:
540
+ services_dict = json.load(file)
541
+ else:
542
+ services_dict = {}
543
+
536
544
  try:
537
545
  result = subprocess.run(
538
546
  ["gcloud", "run", "services", "describe", service_name, "--project", project, "--region", region, "--format=json"],
@@ -544,6 +552,14 @@ def get_cloud_run_service_url(project, region, service_name):
544
552
 
545
553
  service = json.loads(result.stdout.decode())
546
554
  service_url = service['status']['url']
555
+
556
+ # Update the services dictionary
557
+ services_dict[service_name] = service_url
558
+
559
+ # Write the updated dictionary back to the file
560
+ with open(file_path, 'w') as file:
561
+ json.dump(services_dict, file, indent=4)
562
+
547
563
  return service_url
548
564
  except Exception as e:
549
565
  console.print(f"[bold red]ERROR: An unexpected error occurred: {e}[/bold red]")
@@ -7,6 +7,7 @@ from .safety import genai_safety
7
7
  from typing import TYPE_CHECKING, Union
8
8
 
9
9
  import json
10
+ from collections import deque
10
11
 
11
12
  try:
12
13
  import google.generativeai as genai
@@ -254,7 +255,9 @@ class GenAIFunctionProcessor:
254
255
  if not isinstance(fn_exec, genai.protos.FunctionDeclaration):
255
256
  # Execute the function with the provided parameters
256
257
  result = fn_exec(**params_obj)
257
- log.info(f"Got result from {function_name}: {result}")
258
+ log.info(f"Got result from {function_name}: {result} of type: {type(result)}")
259
+ if not isinstance(result, str):
260
+ log.warning(f"Tool functions should return strings: {function_name} returned type: {type(result)}")
258
261
  else:
259
262
  fn_result = type(fn).to_dict(fn)
260
263
  result = fn_result.get("result")
@@ -370,12 +373,12 @@ class GenAIFunctionProcessor:
370
373
  }
371
374
  functions_called =[]
372
375
  function_results = []
376
+ # Initialize token queue to ensure sequential processing
377
+ token_queue = deque()
373
378
 
374
379
  while guardrail < guardrail_max:
375
380
 
376
- callback.on_llm_new_token(
377
- token=f"\n----Loop [{guardrail}] Start------\nFunctions: {list(self.funcs.keys())}\n"
378
- )
381
+ token_queue.append(f"\n----Loop [{guardrail}] Start------\nFunctions: {list(self.funcs.keys())}\n")
379
382
 
380
383
  content_parse = ""
381
384
  for i, chunk in enumerate(content):
@@ -387,13 +390,13 @@ class GenAIFunctionProcessor:
387
390
  response = []
388
391
 
389
392
  try:
390
- callback.on_llm_new_token(token="\n= Calling Agent\n")
393
+ token_queue.append("\n= Calling Agent =\n")
391
394
  response = chat.send_message(content, stream=True)
392
395
 
393
396
  except Exception as e:
394
397
  msg = f"Error sending {content} to model: {str(e)} - {traceback.format_exc()}"
395
398
  log.info(msg)
396
- callback.on_llm_new_token(token=msg)
399
+ token_queue.append(msg)
397
400
  break
398
401
 
399
402
  loop_metadata = response.usage_metadata
@@ -403,11 +406,10 @@ class GenAIFunctionProcessor:
403
406
  "candidates_token_count": usage_metadata["candidates_token_count"] + (loop_metadata.candidates_token_count or 0),
404
407
  "total_token_count": usage_metadata["total_token_count"] + (loop_metadata.total_token_count or 0),
405
408
  }
406
- callback.on_llm_new_token(token=(
407
- "\n-- Agent response\n"
408
- f"prompt_token_count: [{loop_metadata.prompt_token_count}]/[{usage_metadata['prompt_token_count']}] "
409
- f"candidates_token_count: [{loop_metadata.candidates_token_count}]/[{usage_metadata['candidates_token_count']}] "
410
- f"total_token_count: [{loop_metadata.total_token_count}]/[{usage_metadata['total_token_count']}] \n"
409
+ token_queue.append((
410
+ "\n-- Agent response -- "
411
+ f"Loop tokens: [{loop_metadata.prompt_token_count}]/[{usage_metadata['prompt_token_count']}] "
412
+ f"Session tokens: [{loop_metadata.total_token_count}]/[{usage_metadata['total_token_count']}] \n"
411
413
  ))
412
414
  loop_metadata = None
413
415
 
@@ -419,20 +421,20 @@ class GenAIFunctionProcessor:
419
421
  try:
420
422
  if hasattr(chunk, 'text') and isinstance(chunk.text, str):
421
423
  token = chunk.text
422
- callback.on_llm_new_token(token=token)
424
+ token_queue.append(token)
423
425
  big_text += token
424
426
  this_text += token
425
427
  else:
426
428
  log.info("skipping chunk with no text")
427
429
 
428
430
  except ValueError as err:
429
- callback.on_llm_new_token(token=f"{str(err)} for {chunk=}")
431
+ token_queue.append(f"{str(err)} for {chunk=}")
430
432
 
431
433
  executed_responses = self.process_funcs(response)
432
434
  log.info(f"[{guardrail}] {executed_responses=}")
433
435
 
434
436
  if executed_responses:
435
- callback.on_llm_new_token(token="\nAgent function execution:\n")
437
+ token_queue.append("\n-- Agent Actions:\n")
436
438
  for executed_response in executed_responses:
437
439
  token = ""
438
440
  fn = executed_response.function_response.name
@@ -442,10 +444,13 @@ class GenAIFunctionProcessor:
442
444
  log.info(fn_log)
443
445
  functions_called.append(fn_log)
444
446
  function_results.append(fn_result)
445
- callback.on_llm_new_token(token=f"\n--- function calling: {fn_log} ...\n")
447
+ token_queue.append(f"\n-- {fn_log} ...executing...\n") if fn != "decide_to_go_on" else ""
448
+ while token_queue:
449
+ token = token_queue.popleft()
450
+ callback.on_llm_new_token(token=token)
446
451
 
447
452
  try:
448
- # Convert MapComposite to a standard Python dictionary
453
+ # Convert MapComposite to a standard Python dictionary
449
454
  if isinstance(fn_result, proto.marshal.collections.maps.MapComposite):
450
455
  fn_result = dict(fn_result)
451
456
  fn_result_json = json.loads(fn_result)
@@ -463,12 +468,12 @@ class GenAIFunctionProcessor:
463
468
  log.info(f"{fn_result_json} {fn_result=} {type(fn_result)}")
464
469
  go_on_args = fn_result_json
465
470
  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')}"
471
+ token = f"\n{'STOPPING' if not go_on_args.get('go_on') else 'CONTINUE'}: {go_on_args.get('chat_summary')}\n"
467
472
  else:
468
473
  log.warning(f"{fn_result_json} did not work for decide_to_go_on")
469
474
  token = f"Error calling decide_to_go_on with {fn_result_json}\n"
470
475
  else:
471
- token = f"--- {fn} call result: \n"
476
+ token = f"--- {fn}() result --- \n"
472
477
  if fn_result_json:
473
478
  if fn_result_json.get('stdout'):
474
479
  text = fn_result_json.get('stdout').encode('utf-8').decode('unicode_escape')
@@ -479,14 +484,14 @@ class GenAIFunctionProcessor:
479
484
  if not fn_result_json.get('stdout') and fn_result_json.get('stderr'):
480
485
  token += f"{fn_result}\n"
481
486
  else:
482
- token += f"{fn_result}\n--- {fn} result end ---\n"
487
+ token += f"{fn_result}\n--- end ---\n"
483
488
 
484
489
  big_text += token
485
490
  this_text += token
486
- callback.on_llm_new_token(token=token)
491
+ token_queue.append(token)
487
492
  else:
488
493
  token = "\nNo function executions were found\n"
489
- callback.on_llm_new_token(token=token)
494
+ token_queue.append(token)
490
495
  big_text += token
491
496
  this_text += token
492
497
 
@@ -497,20 +502,26 @@ class GenAIFunctionProcessor:
497
502
  log.warning(f"[{guardrail}] No content created this loop")
498
503
  content.append(f"Agent: No response was found for loop [{guardrail}]")
499
504
 
500
- callback.on_llm_new_token(
501
- token=f"\n----Loop [{guardrail}] End------\n{usage_metadata}\n----------------------"
502
- )
505
+ token_queue.append(f"\n----Loop [{guardrail}] End------\n{usage_metadata}\n----------------------")
503
506
 
504
507
  go_on_check = self.check_function_result("decide_to_go_on", {"go_on": False})
505
508
  if go_on_check:
506
509
  log.info("Breaking agent loop")
507
510
  break
508
511
 
512
+ while token_queue:
513
+ token = token_queue.popleft()
514
+ callback.on_llm_new_token(token=token)
515
+
509
516
  guardrail += 1
510
517
  if guardrail > guardrail_max:
511
- log.warning("Guardrail kicked in, more than 10 loops")
518
+ log.warning(f"Guardrail kicked in, more than {guardrail_max} loops")
512
519
  break
513
520
 
521
+ while token_queue:
522
+ token = token_queue.popleft()
523
+ callback.on_llm_new_token(token=token)
524
+
514
525
  usage_metadata["functions_called"] = functions_called
515
526
  #usage_metadata["function_results"] = function_results
516
527
 
@@ -26,14 +26,12 @@ class ConfigManager:
26
26
  agent = config.vacConfig("agent")
27
27
  ```
28
28
  """
29
- print(f"Current working directory: {os.getcwd()}")
30
29
  if os.getenv("VAC_CONFIG_FOLDER") is None:
31
30
  print("WARNING: No VAC_CONFIG_FOLDER environment variable was specified")
32
31
  local_config_folder = os.path.join(os.getcwd(), "config")
33
- if os.path.isdir(local_config_folder):
34
- print(f"Found local config folder {local_config_folder} - will overwrite any global configurations")
35
- else:
32
+ if not os.path.isdir(local_config_folder):
36
33
  local_config_folder = None
34
+
37
35
  if os.getenv("VAC_CONFIG_FOLDER") is None and local_config_folder is None:
38
36
  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.")
39
37
 
@@ -151,7 +149,7 @@ class ConfigManager:
151
149
 
152
150
  self.config_cache[filename] = (config, datetime.now())
153
151
  if is_local:
154
- log.warning(f"Local configuration override for {filename} via {self.local_config_folder}")
152
+ log.info(f"Local configuration override for {filename} via {self.local_config_folder}")
155
153
  return config
156
154
 
157
155
  def _check_and_reload_configs(self):
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.92.4
3
+ Version: 0.92.6
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.4.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.92.6.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -42,7 +42,7 @@ sunholo/chunker/publish.py,sha256=AX5u-fcyDytED67IfizMzvOMcYPXEo6XBJvyk_7maK8,29
42
42
  sunholo/chunker/pubsub.py,sha256=48bhuAcszN7LGe3-ksPSLHHhq0uKxiXOrizck5qpcP0,1012
43
43
  sunholo/chunker/splitter.py,sha256=QLAEsJOpEYFZr9-UGZUuAlNVyjfCWb8jvzCHg0rVShE,6751
44
44
  sunholo/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- sunholo/cli/chat_vac.py,sha256=jTmCt62U4uqJjeGp_XfIbxnafAAOhQAJMi8TxSkeKlM,23164
45
+ sunholo/cli/chat_vac.py,sha256=sYPzUDwwwebJvIobv3GRW_xbQQ4BTy9G-WHdarGCHB0,23705
46
46
  sunholo/cli/cli.py,sha256=q-ATmnWnc_PPo2q31xhqpp-m3GtOSBoqh0gvMeSo4XU,4374
47
47
  sunholo/cli/cli_init.py,sha256=9-w-7OW1yl5QRedkKg_W_-LuPia9t79QsSWq_4vUG6A,8298
48
48
  sunholo/cli/configs.py,sha256=QUM9DvKOdZmEQRM5uI3Nh887T0YDiSMr7O240zTLqws,4546
@@ -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=u4eOU31IaIybia7i40LfwezwcWJbADlAn3qIvio802Y,23789
89
+ sunholo/genai/process_funcs_cls.py,sha256=1yDVh7Gi5qX0FMzV__8k3vn3BJ7AreX9CvPxM_QPFkU,24235
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=D8lrqubVcUkHQLjfMxYOgqdwAoAJB8gcv7knVqgCzAo,10015
131
+ sunholo/utils/config_class.py,sha256=aNhxhEHIxRvqQNq_9wFJt1yM9U1ypahCVZ3NzPWuay4,9843
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.4.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
148
- sunholo-0.92.4.dist-info/METADATA,sha256=YWRorSv9yV1LmiVzQx58WwE0a0fku5SXST4kHqRvnVo,7806
149
- sunholo-0.92.4.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
150
- sunholo-0.92.4.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
151
- sunholo-0.92.4.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
152
- sunholo-0.92.4.dist-info/RECORD,,
147
+ sunholo-0.92.6.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
148
+ sunholo-0.92.6.dist-info/METADATA,sha256=qQpD3u4tg37RVQcIZH2Kb0cemizMQQWS-PfHgHE4nYo,7806
149
+ sunholo-0.92.6.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
150
+ sunholo-0.92.6.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
151
+ sunholo-0.92.6.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
152
+ sunholo-0.92.6.dist-info/RECORD,,