sunholo 0.56.2__py3-none-any.whl → 0.56.5__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/__init__.py CHANGED
@@ -1,34 +0,0 @@
1
- from . import agents
2
- from . import archive
3
- from . import auth
4
- from . import bots
5
- from . import chunker
6
- from . import components
7
- from . import database
8
- from . import embedder
9
- from . import gcs
10
- from . import langfuse
11
- from . import lookup
12
- from . import patches
13
- from . import qna
14
- from . import streaming
15
- from . import utils
16
- import logging
17
-
18
- __all__ = ['agents',
19
- 'archive',
20
- 'auth',
21
- 'bots',
22
- 'chunker',
23
- 'components',
24
- 'database',
25
- 'embedder',
26
- 'gcs',
27
- 'langfuse',
28
- 'lookup',
29
- 'patches',
30
- 'qna',
31
- 'streaming',
32
- 'utils',
33
- 'logging']
34
-
sunholo/cli/cli.py CHANGED
@@ -1,12 +1,82 @@
1
- # sunholo/cli/cli.py
2
1
  import argparse
2
+ try:
3
+ from google.cloud import build_v1
4
+ except ImportError:
5
+ build_v1 = None
3
6
 
4
- def main():
5
- parser = argparse.ArgumentParser(description="sunholo CLI tool.")
6
- parser.add_argument('--echo', help='Echo the string you use here')
7
- args = parser.parse_args()
8
- if args.echo:
9
- print(args.echo)
7
+ from ..logging import log
8
+
9
+ def trigger_build(args):
10
+ """
11
+ Triggers a Google Cloud Build using an existing build trigger configured in GCP.
12
+
13
+ Args:
14
+ args: argparse.Namespace containing the command line arguments specified for the 'deploy' command.
15
+
16
+ Example:
17
+ trigger_build(args) where args contains project_id, trigger_id, repo_name, and branch_name.
18
+ """
19
+ if not build_v1:
20
+ log.warning("Can't deploy - google-cloud-build not installed, enable via `pip install sunholo[gcp]")
21
+
22
+ return None
23
+
24
+ client = build_v1.services.cloud_build.CloudBuildClient()
25
+ # Assuming the build source uses the path to the cloudbuild.yaml if specified.
26
+ source = build_v1.RepoSource(
27
+ project_id=args.project_id,
28
+ repo_name=args.repo_name,
29
+ branch_name=args.branch_name,
30
+ substitutions=args.substitutions,
31
+ dir=args.config_path # Path to directory containing cloudbuild.yaml
32
+ )
33
+ request = build_v1.RunBuildTriggerRequest(
34
+ project_id=args.project_id,
35
+ trigger_id=args.trigger_id,
36
+ source=source
37
+ )
38
+ operation = client.run_build_trigger(request)
39
+ print(f"Triggered build with id: {operation.metadata.build.id}")
40
+
41
+ def setup_deploy_subparser(subparsers):
42
+ """
43
+ Sets up an argparse subparser for the 'deploy' command.
44
+
45
+ Example command:
46
+ ```bash
47
+ sunholo deploy --project_id "my-gcp-project" --trigger_id "my-trigger-id" --repo_name "my-repo"
48
+ ```
49
+ """
50
+ deploy_parser = subparsers.add_parser('deploy', help='Triggers a deployment using an existing Google Cloud Build trigger.')
51
+ deploy_parser.add_argument('--project_id', required=True, help='Google Cloud Project ID required for deployment.')
52
+ deploy_parser.add_argument('--trigger_id', required=True, help='Google Cloud Build Trigger ID required for deployment.')
53
+ deploy_parser.add_argument('--repo_name', required=True, help='Name of the linked repository in Google Cloud Source Repositories required for deployment.')
54
+ deploy_parser.add_argument('--branch_name', default='main', help='Branch name to trigger the build from, defaults to "main".')
55
+ deploy_parser.add_argument('--config_path', default='.', help='Path to the directory containing the cloudbuild.yaml file, defaults to current directory.')
56
+ deploy_parser.set_defaults(func=trigger_build)
57
+
58
+ def main(args=None):
59
+ """
60
+ Entry point for the sunholo console script. This function parses command line arguments
61
+ and invokes the appropriate functionality based on the user input.
62
+
63
+ Example commands:
64
+ ```bash
65
+ sunholo deploy --project_id "my-gcp-project" --trigger_id "my-trigger-id" --repo_name "my-repo" --branch_name "dev" --config_path "app/vac/my_vac/"
66
+ ```
67
+ """
68
+ parser = argparse.ArgumentParser(description="sunholo CLI tool for deploying applications using Google Cloud Build.")
69
+ subparsers = parser.add_subparsers(title='commands', description='Valid commands', help='`sunholo deploy --help`', dest='command', required=True)
70
+
71
+ # Setup deploy command
72
+ setup_deploy_subparser(subparsers)
73
+
74
+ args = parser.parse_args(args)
75
+
76
+ if hasattr(args, 'func'):
77
+ args.func(args)
78
+ else:
79
+ parser.print_help()
10
80
 
11
81
  if __name__ == "__main__":
12
82
  main()
sunholo/logging.py CHANGED
@@ -214,9 +214,6 @@ def setup_logging(logger_name=None, log_level=logging.INFO, project_id=None):
214
214
  if is_logging_setup(logger):
215
215
  return logger
216
216
 
217
- if project_id is None:
218
- project_id = get_gcp_project()
219
-
220
217
  if logger_name is None:
221
218
  logger_name = "sunholo"
222
219
 
@@ -227,6 +224,8 @@ def setup_logging(logger_name=None, log_level=logging.INFO, project_id=None):
227
224
  print("Found GOOGLE_CLOUD_LOGGING=1 but no GCP Client available, install via `pip install sunholo[gcp]` and/or authenticate")
228
225
 
229
226
  if Client and os.environ.get('GOOGLE_CLOUD_LOGGING') == "1":
227
+ if project_id is None:
228
+ project_id = get_gcp_project()
230
229
  # Instantiate the GoogleCloudLogging class
231
230
  gc_logger = GoogleCloudLogging(project_id, log_level=log_level, logger_name=logger_name)
232
231
  else:
sunholo/qna/retry.py CHANGED
@@ -33,7 +33,7 @@ def retry_qna(qa_function, question, max_retries=1, initial_delay=5):
33
33
  except ReadTimeout:
34
34
  if retry == max_retries - 1:
35
35
  raise
36
- except Exception as err:
36
+ except Exception:
37
37
  delay = initial_delay * (retry + 1)
38
38
  log.error(f"General error: {traceback.format_exc()}")
39
39
  time.sleep(delay)
@@ -23,6 +23,7 @@ from ..qna.parsers import parse_output
23
23
 
24
24
  from ..logging import log
25
25
  from ..utils import load_config_key
26
+ from ..utils.parsers import check_kwargs_support
26
27
 
27
28
  from .langserve import parse_langserve_token, parse_langserve_token_async
28
29
 
@@ -34,6 +35,9 @@ def start_streaming_chat(question,
34
35
  wait_time=2,
35
36
  timeout=120, # Timeout in seconds (2 minutes)
36
37
  **kwargs):
38
+
39
+ if not check_kwargs_support(qna_func):
40
+ yield "No **kwargs in qna_func - please add it"
37
41
 
38
42
  # Immediately yield to indicate the process has started.
39
43
  yield "Thinking...\n"
@@ -49,7 +53,10 @@ def start_streaming_chat(question,
49
53
  def start_chat(stop_event, result_queue, exception_queue):
50
54
  # autogen_qna(user_input, vector_name, chat_history=None):
51
55
  try:
52
- final_result = qna_func(question, vector_name, chat_history, callback=chat_callback_handler, **kwargs)
56
+ final_result = qna_func(question=question,
57
+ vector_name=vector_name,
58
+ chat_history=chat_history,
59
+ callback=chat_callback_handler, **kwargs)
53
60
  result_queue.put(final_result)
54
61
  except Exception as e:
55
62
  exception_queue.put(e)
sunholo/utils/__init__.py CHANGED
@@ -1 +1 @@
1
- from .config import fetch_config, load_config_key, load_config
1
+ from .config import load_config_key, load_config
sunholo/utils/config.py CHANGED
@@ -18,54 +18,6 @@ import yaml
18
18
  from datetime import datetime, timedelta
19
19
  from collections import defaultdict
20
20
 
21
- try:
22
- from google.cloud import storage
23
- except ImportError:
24
- storage = None
25
-
26
- def fetch_config(bucket_name: str, blob_name: str):
27
- """
28
- Fetch the configuration file from a Google Cloud Storage bucket.
29
-
30
- Args:
31
- bucket_name (str): The name of the GCS bucket.
32
- blob_name (str): The name of the blob/file to fetch.
33
-
34
- Returns:
35
- datetime or None: The last modified time of the file, or None if the blob does not exist.
36
-
37
- Example:
38
- ```python
39
- last_updated = fetch_config('my-bucket', 'config.yaml')
40
- if last_updated:
41
- print(f'Configuration file was last updated on {last_updated}')
42
- else:
43
- print('Configuration file not found in the specified bucket.')
44
- ```
45
- """
46
- from ..logging import log
47
-
48
- if not storage:
49
- log.debug("No google.cloud.storage client installed. Skipping config load from bucket")
50
- return None
51
-
52
- storage_client = storage.Client()
53
-
54
- bucket = storage_client.bucket(bucket_name)
55
- blob = storage.Blob(blob_name, bucket)
56
-
57
- # Check if the file exists
58
- if not blob.exists():
59
- log.info(f"The blob {blob_name} does not exist in the bucket {bucket_name}")
60
- return None
61
-
62
- # Download the file to a local file
63
- blob.download_to_filename(blob_name)
64
-
65
- # Get the blob's updated time
66
- updated_time = blob.updated
67
-
68
- return updated_time
69
21
 
70
22
  def get_module_filepath(filepath: str):
71
23
  """
@@ -105,11 +57,14 @@ def load_all_configs():
105
57
  from ..logging import log
106
58
 
107
59
  config_folder = os.getenv("_CONFIG_FOLDER", os.getcwd())
108
- log.debug(f"Loading all configs from folder: {config_folder}")
60
+ config_folder = os.path.join(config_folder, "config")
61
+
62
+ log.info(f"Loading all configs from folder: {config_folder}")
109
63
  current_time = datetime.now()
110
64
 
111
65
  configs_by_kind = defaultdict(dict)
112
66
  for filename in os.listdir(config_folder):
67
+ log.info(f"config file: {filename}")
113
68
  if filename.endswith(('.yaml', '.yml', '.json')):
114
69
  config_file = os.path.join(config_folder, filename)
115
70
 
@@ -117,7 +72,7 @@ def load_all_configs():
117
72
  if filename in config_cache:
118
73
  cached_config, cache_time = config_cache[filename]
119
74
  if (current_time - cache_time) < timedelta(minutes=5):
120
- log.debug(f"Returning cached config for {filename}")
75
+ log.info(f"Returning cached config for {filename}")
121
76
  config = cached_config
122
77
  else:
123
78
  config = reload_config_file(config_file, filename)
@@ -234,6 +189,17 @@ def load_config_key(key: str, vector_name: str, filename: str=None, kind: str=No
234
189
  assert isinstance(vector_name, str), f"vector_name must be a string, got a {type(vector_name)}"
235
190
 
236
191
  configs_by_kind = load_all_configs()
192
+ log.info(f"configs by kind: {configs_by_kind}")
193
+
194
+ if kind:
195
+ log.info(f"Got kind: {kind} - applying to configs")
196
+
197
+ if filename:
198
+ log.warning(f"Got filename argument: {filename} for config - deprecated - use `kind='vacConfig'` instead")
199
+
200
+ if not configs_by_kind:
201
+ log.warning("Did not load configs via folder")
202
+
237
203
  if kind and configs_by_kind.get(kind):
238
204
  config = configs_by_kind[kind]
239
205
  filename = kind
sunholo/utils/parsers.py CHANGED
@@ -118,4 +118,22 @@ def remove_whitespace(page_content: str):
118
118
  print(cleaned_text) # Outputs 'Hello, world! This is an example.'
119
119
  ```
120
120
  """
121
- return page_content.replace("\n", " ").replace("\r", " ").replace("\t", " ").replace(" ", " ")
121
+ return page_content.replace("\n", " ").replace("\r", " ").replace("\t", " ").replace(" ", " ")
122
+
123
+ def check_kwargs_support(func):
124
+ """
125
+ Check if the function 'func' accepts arbitrary keyword arguments (**kwargs).
126
+
127
+ Args:
128
+ func (callable): The function to check.
129
+
130
+ Returns:
131
+ bool: True if **kwargs is accepted, False otherwise.
132
+ """
133
+ import inspect
134
+
135
+ sig = inspect.signature(func)
136
+ for param in sig.parameters.values():
137
+ if param.kind == param.VAR_KEYWORD:
138
+ return True
139
+ return False
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.56.2
3
+ Version: 0.56.5
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.56.2.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.56.5.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -27,6 +27,7 @@ Requires-Dist: flask ; extra == 'all'
27
27
  Requires-Dist: google-cloud-aiplatform ; extra == 'all'
28
28
  Requires-Dist: google-api-python-client ; extra == 'all'
29
29
  Requires-Dist: google-cloud-alloydb-connector[pg8000] ; extra == 'all'
30
+ Requires-Dist: google-cloud-build ; extra == 'all'
30
31
  Requires-Dist: google-cloud-logging ; extra == 'all'
31
32
  Requires-Dist: google-cloud-storage ; extra == 'all'
32
33
  Requires-Dist: google-cloud-pubsub ; extra == 'all'
@@ -54,6 +55,7 @@ Requires-Dist: pg8000 ; extra == 'database'
54
55
  Requires-Dist: lancedb ; extra == 'database'
55
56
  Provides-Extra: gcp
56
57
  Requires-Dist: google-cloud-aiplatform ; extra == 'gcp'
58
+ Requires-Dist: google-cloud-build ; extra == 'gcp'
57
59
  Requires-Dist: google-cloud-storage ; extra == 'gcp'
58
60
  Requires-Dist: google-cloud-logging ; extra == 'gcp'
59
61
  Requires-Dist: google-cloud-pubsub ; extra == 'gcp'
@@ -1,5 +1,5 @@
1
- sunholo/__init__.py,sha256=hEN0kOEikUGBot_YIMra1nnPNmcwmO_kwvPOmLW8-_8,692
2
- sunholo/logging.py,sha256=wvaT33baueD2VV5oP84duhwKKpH4os_3LtqZVWaGPIw,11226
1
+ sunholo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ sunholo/logging.py,sha256=_poZ61TbLl6yHox2eO78BvIGQCUCrAIjWio70sGJIag,11233
3
3
  sunholo/agents/__init__.py,sha256=CnlbVohPt-Doth9PyROSlN3P8xMV9j9yS19YE-wCS90,341
4
4
  sunholo/agents/chat_history.py,sha256=PbwYmw1TwzI8H-cwQIGgHZ6UIr2Qb-JWow0RG3ayLM8,5195
5
5
  sunholo/agents/dispatch_to_qa.py,sha256=kWrO-CJel5kJAyyCShShpACUuZpqDOP7DN8vo_7ciao,8056
@@ -31,7 +31,7 @@ sunholo/chunker/pdfs.py,sha256=daCZ1xjn1YvxlifIyxskWNpLJLe-Q9D_Jq12MWx3tZo,2473
31
31
  sunholo/chunker/publish.py,sha256=PoT8q3XJeFCg10WrLkYhuaaXIrGVkvUD3-R9IfoWoH4,2703
32
32
  sunholo/chunker/splitter.py,sha256=CZ33xVWeYdjckd1VTrZnxuLypzzn-yKXQBFZaN7UcjI,6697
33
33
  sunholo/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- sunholo/cli/cli.py,sha256=i6L729GLkxcYNGFtujYxrkoILUxMvNiHmv_-Zlo7nAY,304
34
+ sunholo/cli/cli.py,sha256=axhTubWv1IUBEn1nBf-6iuHCiywe6oTMyPL8tgoyCJs,3354
35
35
  sunholo/components/__init__.py,sha256=RJGNEihwvRIiDScKis04RHJv4yZGI1UpXlOmuCptNZI,208
36
36
  sunholo/components/llm.py,sha256=clZktcwEOwZwHE0Bl8hDRt5aDhOOEgCi1STcW0PBxc8,10430
37
37
  sunholo/components/prompt.py,sha256=eZSghXkIlRzXiSrzgkG7e5ytUYq6R6LV-qjHU8jStig,6353
@@ -72,20 +72,20 @@ sunholo/pubsub/process_pubsub.py,sha256=64hvqMsxbBrf0WGJsprz_SXf9FpjeszAIsqUSBlJ
72
72
  sunholo/pubsub/pubsub_manager.py,sha256=M85QPCXYBPzmE8Ha0FYHdzpA-LRX9p3lu6b-UAHAyac,6400
73
73
  sunholo/qna/__init__.py,sha256=F8q1uR_HreoSX0IfmKY1qoSwIgXhO2Q8kuDSxh9_-EE,28
74
74
  sunholo/qna/parsers.py,sha256=Qn7lYsO2daWN0kDRGop5CkamIPq9wWFPEB1cP6Is7Ng,1585
75
- sunholo/qna/retry.py,sha256=hAcqCZchAG1610G6huPev4ymDdO2G5tT3mrK28dxlAs,2028
75
+ sunholo/qna/retry.py,sha256=gFgOf9AxrZMIO9OwOYu1EW7rhNhyfnw_o4XAsNLBOVQ,2021
76
76
  sunholo/streaming/__init__.py,sha256=k8dBqhzyS1Oi6NfADtRtWfnPtU1FU2kQz-YxH9yrNeQ,197
77
77
  sunholo/streaming/content_buffer.py,sha256=hr2ySHOTK1zw_3u-JrKwoomsAAdda2VcOxjkvJLcUuM,6596
78
78
  sunholo/streaming/langserve.py,sha256=6isOvFwZBfmiQY5N41PYPyrdJj9IgJXXHLfTzPvewGw,6299
79
- sunholo/streaming/streaming.py,sha256=PIdz6un_ytTcOLEnEP_VyJFKZrQq3-ZbmrVHQDEap-A,16425
79
+ sunholo/streaming/streaming.py,sha256=TLLBamDs5ihvA77I30xAXu_J8vMVUmhyeJFJkTN9ess,16723
80
80
  sunholo/summarise/__init__.py,sha256=MZk3dblUMODcPb1crq4v-Z508NrFIpkSWNf9FIO8BcU,38
81
81
  sunholo/summarise/summarise.py,sha256=C3HhjepTjUhUC8FLk4jMQIBvq1BcORniwuTFHjPVhVo,3784
82
- sunholo/utils/__init__.py,sha256=MxuxoJ-oOie_skGnB4mOagVYjzvfmX9Gz9N5heI8azM,62
83
- sunholo/utils/config.py,sha256=qkcK1T2AvobmkTp8D-SNXLBxe86TKCuquA_5TkrVfk8,9589
82
+ sunholo/utils/__init__.py,sha256=G11nN_6ATjxpuMfG_BvcUr9UU8onPIgkpTK6CjOcbr8,48
83
+ sunholo/utils/config.py,sha256=NW2FFyNNTwCyopOvSzDQ0I0l92LAfJJ7hEzatSuoZho,8689
84
84
  sunholo/utils/gcp.py,sha256=B2G1YKjeD7X9dqO86Jrp2vPuFwZ223Xl5Tg09Ndw-oc,5760
85
- sunholo/utils/parsers.py,sha256=E-M7s3_rPviT5zCqQHzhb1DwYmz5a1J472ZVazx10M8,3400
86
- sunholo-0.56.2.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
87
- sunholo-0.56.2.dist-info/METADATA,sha256=bnQq2e718arq78-JQhG5lJJgr-zbvwwoj7vi6QLVQTo,6515
88
- sunholo-0.56.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
89
- sunholo-0.56.2.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
90
- sunholo-0.56.2.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
91
- sunholo-0.56.2.dist-info/RECORD,,
85
+ sunholo/utils/parsers.py,sha256=OrHmASqIbI45atVOhiGodgLvnfrzkvVzyHnSvAXD89I,3841
86
+ sunholo-0.56.5.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
87
+ sunholo-0.56.5.dist-info/METADATA,sha256=h5wDzUzuL3TrTKVTKpGyOS8D-wFgOZAJUugJLYvj8T4,6617
88
+ sunholo-0.56.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
89
+ sunholo-0.56.5.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
90
+ sunholo-0.56.5.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
91
+ sunholo-0.56.5.dist-info/RECORD,,