sunholo 0.55.15__tar.gz → 0.56.1__tar.gz

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.
Files changed (98) hide show
  1. {sunholo-0.55.15 → sunholo-0.56.1}/PKG-INFO +5 -3
  2. {sunholo-0.55.15 → sunholo-0.56.1}/setup.py +9 -2
  3. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/flask/qna_routes.py +0 -13
  4. sunholo-0.56.1/sunholo/cli/cli.py +12 -0
  5. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/components/llm.py +14 -14
  6. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/logging.py +7 -2
  7. sunholo-0.56.1/sunholo/patches/langchain/__init__.py +0 -0
  8. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/utils/config.py +63 -3
  9. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo.egg-info/PKG-INFO +5 -3
  10. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo.egg-info/SOURCES.txt +3 -0
  11. sunholo-0.56.1/sunholo.egg-info/entry_points.txt +2 -0
  12. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo.egg-info/requires.txt +3 -1
  13. {sunholo-0.55.15 → sunholo-0.56.1}/LICENSE.txt +0 -0
  14. {sunholo-0.55.15 → sunholo-0.56.1}/MANIFEST.in +0 -0
  15. {sunholo-0.55.15 → sunholo-0.56.1}/README.md +0 -0
  16. {sunholo-0.55.15 → sunholo-0.56.1}/setup.cfg +0 -0
  17. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/__init__.py +0 -0
  18. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/__init__.py +0 -0
  19. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/chat_history.py +0 -0
  20. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/dispatch_to_qa.py +0 -0
  21. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/fastapi/__init__.py +0 -0
  22. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/fastapi/base.py +0 -0
  23. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/fastapi/qna_routes.py +0 -0
  24. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/flask/__init__.py +0 -0
  25. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/flask/base.py +0 -0
  26. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/langserve.py +0 -0
  27. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/pubsub.py +0 -0
  28. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/route.py +0 -0
  29. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/special_commands.py +0 -0
  30. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/agents/test_chat_history.py +0 -0
  31. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/archive/__init__.py +0 -0
  32. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/archive/archive.py +0 -0
  33. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/auth/__init__.py +0 -0
  34. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/auth/run.py +0 -0
  35. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/bots/__init__.py +0 -0
  36. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/bots/discord.py +0 -0
  37. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/bots/webapp.py +0 -0
  38. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/__init__.py +0 -0
  39. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/data_to_embed_pubsub.py +0 -0
  40. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/doc_handling.py +0 -0
  41. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/images.py +0 -0
  42. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/loaders.py +0 -0
  43. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/message_data.py +0 -0
  44. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/pdfs.py +0 -0
  45. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/publish.py +0 -0
  46. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/chunker/splitter.py +0 -0
  47. {sunholo-0.55.15/sunholo/langfuse → sunholo-0.56.1/sunholo/cli}/__init__.py +0 -0
  48. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/components/__init__.py +0 -0
  49. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/components/prompt.py +0 -0
  50. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/components/retriever.py +0 -0
  51. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/components/vectorstore.py +0 -0
  52. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/__init__.py +0 -0
  53. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/alloydb.py +0 -0
  54. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/database.py +0 -0
  55. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/lancedb.py +0 -0
  56. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/sql/sb/create_function.sql +0 -0
  57. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/sql/sb/create_function_time.sql +0 -0
  58. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/sql/sb/create_table.sql +0 -0
  59. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  60. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/sql/sb/return_sources.sql +0 -0
  61. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/sql/sb/setup.sql +0 -0
  62. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/static_dbs.py +0 -0
  63. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/database/uuid.py +0 -0
  64. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/embedder/__init__.py +0 -0
  65. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/embedder/embed_chunk.py +0 -0
  66. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/gcs/__init__.py +0 -0
  67. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/gcs/add_file.py +0 -0
  68. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/gcs/download_url.py +0 -0
  69. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/gcs/metadata.py +0 -0
  70. {sunholo-0.55.15/sunholo/llamaindex → sunholo-0.56.1/sunholo/langfuse}/__init__.py +0 -0
  71. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/langfuse/callback.py +0 -0
  72. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/langfuse/prompts.py +0 -0
  73. {sunholo-0.55.15/sunholo/lookup → sunholo-0.56.1/sunholo/llamaindex}/__init__.py +0 -0
  74. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/llamaindex/generate.py +0 -0
  75. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/llamaindex/import_files.py +0 -0
  76. {sunholo-0.55.15/sunholo/patches → sunholo-0.56.1/sunholo/lookup}/__init__.py +0 -0
  77. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/lookup/model_lookup.yaml +0 -0
  78. {sunholo-0.55.15/sunholo/patches/langchain → sunholo-0.56.1/sunholo/patches}/__init__.py +0 -0
  79. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/patches/langchain/lancedb.py +0 -0
  80. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/patches/langchain/vertexai.py +0 -0
  81. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/pubsub/__init__.py +0 -0
  82. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/pubsub/process_pubsub.py +0 -0
  83. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/pubsub/pubsub_manager.py +0 -0
  84. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/qna/__init__.py +0 -0
  85. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/qna/parsers.py +0 -0
  86. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/qna/retry.py +0 -0
  87. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/streaming/__init__.py +0 -0
  88. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/streaming/content_buffer.py +0 -0
  89. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/streaming/langserve.py +0 -0
  90. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/streaming/streaming.py +0 -0
  91. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/summarise/__init__.py +0 -0
  92. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/summarise/summarise.py +0 -0
  93. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/utils/__init__.py +0 -0
  94. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/utils/gcp.py +0 -0
  95. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo/utils/parsers.py +0 -0
  96. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo.egg-info/dependency_links.txt +0 -0
  97. {sunholo-0.55.15 → sunholo-0.56.1}/sunholo.egg-info/top_level.txt +0 -0
  98. {sunholo-0.55.15 → sunholo-0.56.1}/test/test_dispatch_to_qa.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.55.15
3
+ Version: 0.56.1
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.55.15.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.56.1.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -30,6 +30,7 @@ Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
30
30
  Requires-Dist: google-cloud-logging; extra == "all"
31
31
  Requires-Dist: google-cloud-storage; extra == "all"
32
32
  Requires-Dist: google-cloud-pubsub; extra == "all"
33
+ Requires-Dist: gunicorn; extra == "all"
33
34
  Requires-Dist: httpcore; extra == "all"
34
35
  Requires-Dist: httpx; extra == "all"
35
36
  Requires-Dist: lancedb; extra == "all"
@@ -63,11 +64,12 @@ Requires-Dist: langchain-openai; extra == "openai"
63
64
  Provides-Extra: anthropic
64
65
  Requires-Dist: langchain-anthropic; extra == "anthropic"
65
66
  Provides-Extra: http
66
- Requires-Dist: langfuse; extra == "http"
67
67
  Requires-Dist: fastapi; extra == "http"
68
68
  Requires-Dist: flask; extra == "http"
69
+ Requires-Dist: gunicorn; extra == "http"
69
70
  Requires-Dist: httpcore; extra == "http"
70
71
  Requires-Dist: httpx; extra == "http"
72
+ Requires-Dist: langfuse; extra == "http"
71
73
  Requires-Dist: python-socketio; extra == "http"
72
74
 
73
75
  ## Introduction
@@ -1,7 +1,7 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
3
  # Define your base version
4
- version = '0.55.15'
4
+ version = '0.56.1'
5
5
 
6
6
  setup(
7
7
  name='sunholo',
@@ -16,6 +16,11 @@ setup(
16
16
  url = 'https://github.com/sunholo-data/sunholo-py',
17
17
  download_url=f'https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v{version}.tar.gz',
18
18
  keywords=['llms', 'devops','google_cloud_platform'],
19
+ entry_points={
20
+ 'console_scripts': [
21
+ 'sunholo=sunholo.cli.cli:main',
22
+ ],
23
+ },
19
24
  package_data={
20
25
  'sunholo.database': ['sql/sb/*.sql'],
21
26
  'sunholo.lookup': ['*.yaml']
@@ -38,6 +43,7 @@ setup(
38
43
  "google-cloud-logging",
39
44
  "google-cloud-storage",
40
45
  "google-cloud-pubsub",
46
+ "gunicorn",
41
47
  "httpcore",
42
48
  "httpx",
43
49
  "lancedb",
@@ -76,11 +82,12 @@ setup(
76
82
  "langchain-anthropic",
77
83
  ],
78
84
  'http': [
79
- "langfuse",
80
85
  "fastapi",
81
86
  "flask",
87
+ "gunicorn",
82
88
  "httpcore",
83
89
  "httpx",
90
+ "langfuse",
84
91
  "python-socketio",
85
92
  ]
86
93
  },
@@ -23,13 +23,6 @@ from ...streaming import start_streaming_chat
23
23
  from ...archive import archive_qa
24
24
  from ...logging import log
25
25
  from ...utils.config import load_config
26
-
27
- try:
28
- from langfuse import Langfuse
29
- langfuse = Langfuse()
30
- except ImportError as err:
31
- print(f"No langfuse installed for agents.flask.register_qna_routes, install via `pip install sunholo[http]` - {str(err)}")
32
- langfuse = None
33
26
 
34
27
  try:
35
28
  from flask import request, jsonify, Response
@@ -103,9 +96,6 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
103
96
  generation.end(output=response)
104
97
  span.end(output=response)
105
98
  trace.update(output=response)
106
-
107
- if langfuse:
108
- langfuse.flush()
109
99
 
110
100
  return response
111
101
 
@@ -153,9 +143,6 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
153
143
  if trace:
154
144
  span.end(output=jsonify(bot_output))
155
145
  trace.update(output=jsonify(bot_output))
156
-
157
- if langfuse:
158
- langfuse.flush()
159
146
 
160
147
  return jsonify(bot_output)
161
148
 
@@ -0,0 +1,12 @@
1
+ # sunholo/cli/cli.py
2
+ import argparse
3
+
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)
10
+
11
+ if __name__ == "__main__":
12
+ main()
@@ -19,7 +19,7 @@ import os
19
19
  def pick_llm(vector_name):
20
20
  log.debug('Picking llm')
21
21
 
22
- llm_str = load_config_key("llm", vector_name, filename = "config/llm_config.yaml")
22
+ llm_str = load_config_key("llm", vector_name, kind="vacConfig")
23
23
 
24
24
  if llm_str == 'openai':
25
25
  llm_chat = get_llm_chat(vector_name)
@@ -49,7 +49,7 @@ def pick_llm(vector_name):
49
49
 
50
50
  def pick_streaming(vector_name):
51
51
 
52
- llm_str = load_config_key("llm", vector_name, filename = "config/llm_config.yaml")
52
+ llm_str = load_config_key("llm", vector_name, kind="vacConfig")
53
53
 
54
54
  if llm_str == 'openai' or llm_str == 'gemini' or llm_str == 'vertex':
55
55
  return True
@@ -57,7 +57,7 @@ def pick_streaming(vector_name):
57
57
  return False
58
58
 
59
59
 
60
- def llm_str_to_llm(llm_str, model=None, vector_name=None, config_file="config/llm_config.yaml"):
60
+ def llm_str_to_llm(llm_str, model=None, vector_name=None):
61
61
  if llm_str == 'openai':
62
62
  # Setup for OpenAI LLM
63
63
  from langchain_openai import ChatOpenAI
@@ -79,7 +79,7 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None, config_file="config/ll
79
79
 
80
80
  elif llm_str == 'model_garden':
81
81
  from ..patches.langchain.vertexai import VertexAIModelGarden
82
- model_garden_config = load_config_key("gcp_config", vector_name, filename = config_file)
82
+ model_garden_config = load_config_key("gcp_config", vector_name, kind="vacConfig")
83
83
  if model_garden_config is None:
84
84
  raise ValueError("llm='model_garden' requires a gcp_config entry in config yaml file")
85
85
 
@@ -97,21 +97,21 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None, config_file="config/ll
97
97
  if llm_str is None:
98
98
  raise NotImplementedError(f'No llm implemented for {llm_str}')
99
99
 
100
- def get_llm(vector_name, model=None, config_file="config/llm_config.yaml"):
101
- llm_str = load_config_key("llm", vector_name, filename=config_file)
100
+ def get_llm(vector_name, model=None):
101
+ llm_str = load_config_key("llm", vector_name, kind="vacConfig")
102
102
  #model_lookup_filepath = get_module_filepath("lookup/model_lookup.yaml")
103
103
  #model_lookup, _ = load_config(model_lookup_filepath)
104
104
 
105
105
  if not model:
106
- model = load_config_key("model", vector_name, filename=config_file)
106
+ model = load_config_key("model", vector_name, kind="vacConfig")
107
107
 
108
108
  log.debug(f"Chose LLM: {llm_str}")
109
- return llm_str_to_llm(llm_str, model=model, vector_name=vector_name, config_file=config_file)
109
+ return llm_str_to_llm(llm_str, model=model, vector_name=vector_name, kind="vacConfig")
110
110
 
111
111
  def get_llm_chat(vector_name, model=None, config_file="config/llm_config.yaml"):
112
- llm_str = load_config_key("llm", vector_name, filename=config_file)
112
+ llm_str = load_config_key("llm", vector_name, kind="vacConfig")
113
113
  if not model:
114
- model = load_config_key("model", vector_name, filename=config_file)
114
+ model = load_config_key("model", vector_name, kind="vacConfig")
115
115
 
116
116
  log.debug(f"Chose LLM: {llm_str}")
117
117
  # Configure LLMs based on llm_str
@@ -150,7 +150,7 @@ def get_llm_chat(vector_name, model=None, config_file="config/llm_config.yaml"):
150
150
  return ChatAnthropic(model_name = model, temperature=0)
151
151
  elif llm_str == 'azure':
152
152
  from langchain_openai import AzureChatOpenAI
153
- azure_config = load_config_key("azure", vector_name, filename="config/llm_config.yaml")
153
+ azure_config = load_config_key("azure", vector_name, kind="vacConfig")
154
154
  if not azure_config:
155
155
  raise ValueError("Need to configure azure.config if llm='azure'")
156
156
 
@@ -195,13 +195,13 @@ def get_llm_chat(vector_name, model=None, config_file="config/llm_config.yaml"):
195
195
  def get_embeddings(vector_name):
196
196
 
197
197
  llm_str = None
198
- embed_dict = load_config_key("embedder", vector_name, filename="config/llm_config.yaml")
198
+ embed_dict = load_config_key("embedder", vector_name, kind="vacConfig")
199
199
 
200
200
  if embed_dict:
201
201
  llm_str = embed_dict.get('llm')
202
202
 
203
203
  if llm_str is None:
204
- llm_str = load_config_key("llm", vector_name, filename="config/llm_config.yaml")
204
+ llm_str = load_config_key("llm", vector_name, kind="vacConfig")
205
205
 
206
206
  return pick_embedding(llm_str, vector_name=vector_name)
207
207
 
@@ -227,7 +227,7 @@ def pick_embedding(llm_str: str, vector_name: str=None):
227
227
  elif llm_str == 'azure':
228
228
  from langchain_openai import AzureOpenAIEmbeddings
229
229
 
230
- azure_config = load_config_key("azure", vector_name, filename="config/llm_config.yaml")
230
+ azure_config = load_config_key("azure", vector_name, kind="vacConfig")
231
231
  if not azure_config:
232
232
  raise ValueError("Need to configure azure.config if llm='azure'")
233
233
 
@@ -220,11 +220,16 @@ def setup_logging(logger_name=None, log_level=logging.INFO, project_id=None):
220
220
  if logger_name is None:
221
221
  logger_name = "sunholo"
222
222
 
223
- if Client:
223
+ if Client and os.environ.get('GOOGLE_CLOUD_LOGGING') != "1":
224
+ print("GOOGLE_CLOUD_LOGGING != 1 but authentication with Google Cloud Logging enabled - missing env var setting?")
225
+
226
+ if not Client and os.environ.get('GOOGLE_CLOUD_LOGGING') == "1":
227
+ print("Found GOOGLE_CLOUD_LOGGING=1 but no GCP Client available, install via `pip install sunholo[gcp]` and/or authenticate")
228
+
229
+ if Client and os.environ.get('GOOGLE_CLOUD_LOGGING') == "1":
224
230
  # Instantiate the GoogleCloudLogging class
225
231
  gc_logger = GoogleCloudLogging(project_id, log_level=log_level, logger_name=logger_name)
226
232
  else:
227
- print("Could not find GoogleCloudLogging Client, install via `pip install sunholo[gcp]`")
228
233
  return logger
229
234
 
230
235
  # Setup logging and return the logger instance
File without changes
@@ -16,6 +16,7 @@ import os
16
16
  import json
17
17
  import yaml
18
18
  from datetime import datetime, timedelta
19
+ from collections import defaultdict
19
20
 
20
21
  try:
21
22
  from google.cloud import storage
@@ -95,6 +96,58 @@ def get_module_filepath(filepath: str):
95
96
 
96
97
  # Global cache
97
98
  config_cache = {}
99
+ def load_all_configs():
100
+ """
101
+ Load all configuration files from the specified directory into a dictionary.
102
+ Files are expected to be either YAML or JSON and must contain a 'kind' key at the root.
103
+ Caching is used to avoid reloading files within a 5-minute window.
104
+ """
105
+ from ..logging import log
106
+
107
+ config_folder = os.getenv("_CONFIG_FOLDER", os.getcwd())
108
+ log.debug(f"Loading all configs from folder: {config_folder}")
109
+ current_time = datetime.now()
110
+
111
+ configs_by_kind = defaultdict(dict)
112
+ for filename in os.listdir(config_folder):
113
+ if filename.endswith(('.yaml', '.yml', '.json')):
114
+ config_file = os.path.join(config_folder, filename)
115
+
116
+ # Check cache first
117
+ if filename in config_cache:
118
+ cached_config, cache_time = config_cache[filename]
119
+ if (current_time - cache_time) < timedelta(minutes=5):
120
+ log.debug(f"Returning cached config for {filename}")
121
+ config = cached_config
122
+ else:
123
+ config = reload_config_file(config_file, filename)
124
+ else:
125
+ config = reload_config_file(config_file, filename)
126
+
127
+ kind = config.get('kind')
128
+ if kind:
129
+ configs_by_kind[kind] = config
130
+ else:
131
+ log.warning(f"No 'kind' found in {filename}")
132
+
133
+ return configs_by_kind
134
+
135
+ def reload_config_file(config_file, filename):
136
+ """
137
+ Helper function to load a config file and update the cache.
138
+ """
139
+ from ..logging import log
140
+ with open(config_file, 'r') as file:
141
+ if filename.endswith('.json'):
142
+ config = json.load(file)
143
+ else:
144
+ config = yaml.safe_load(file)
145
+
146
+ config_cache[filename] = (config, datetime.now())
147
+ log.debug(f"Loaded and cached {filename}")
148
+ return config
149
+
150
+
98
151
 
99
152
  def load_config(filename: str=None) -> tuple[dict, str]:
100
153
  """
@@ -156,14 +209,15 @@ def load_config(filename: str=None) -> tuple[dict, str]:
156
209
 
157
210
  return config, filename
158
211
 
159
- def load_config_key(key: str, vector_name: str, filename: str=None):
212
+ def load_config_key(key: str, vector_name: str, filename: str=None, kind: str=None):
160
213
  """
161
214
  Load a specific key from a configuration file.
162
215
 
163
216
  Args:
164
217
  key (str): The key to fetch from the configuration.
165
218
  vector_name (str): The name of the vector in the configuration file.
166
- filename (str, optional): The configuration file name. Defaults to the `_CONFIG_FILE` environment variable.
219
+ filename (str, optional): The configuration file name. Defaults to the `_CONFIG_FILE` environment variable. Deprecated - use 'kind' instead
220
+ kind: (str, optional): Specify the type of configuration to retrieve e.g. 'vacConfig' which will pick from files within `_CONFIG_FOLDER`
167
221
 
168
222
  Returns:
169
223
  str: The value associated with the specified key.
@@ -179,7 +233,13 @@ def load_config_key(key: str, vector_name: str, filename: str=None):
179
233
  assert isinstance(key, str), f"key must be a string got a {type(key)}"
180
234
  assert isinstance(vector_name, str), f"vector_name must be a string, got a {type(vector_name)}"
181
235
 
182
- config, filename = load_config(filename)
236
+ configs_by_kind = load_all_configs()
237
+ if kind and configs_by_kind.get(kind):
238
+ config = configs_by_kind[kind]
239
+ filename = kind
240
+ else:
241
+ config, filename = load_config(filename)
242
+
183
243
  log.info(f"Fetching {key} for {vector_name}")
184
244
  apiVersion = config.get('apiVersion')
185
245
  kind = config.get('kind')
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.55.15
3
+ Version: 0.56.1
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.55.15.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.56.1.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -30,6 +30,7 @@ Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
30
30
  Requires-Dist: google-cloud-logging; extra == "all"
31
31
  Requires-Dist: google-cloud-storage; extra == "all"
32
32
  Requires-Dist: google-cloud-pubsub; extra == "all"
33
+ Requires-Dist: gunicorn; extra == "all"
33
34
  Requires-Dist: httpcore; extra == "all"
34
35
  Requires-Dist: httpx; extra == "all"
35
36
  Requires-Dist: lancedb; extra == "all"
@@ -63,11 +64,12 @@ Requires-Dist: langchain-openai; extra == "openai"
63
64
  Provides-Extra: anthropic
64
65
  Requires-Dist: langchain-anthropic; extra == "anthropic"
65
66
  Provides-Extra: http
66
- Requires-Dist: langfuse; extra == "http"
67
67
  Requires-Dist: fastapi; extra == "http"
68
68
  Requires-Dist: flask; extra == "http"
69
+ Requires-Dist: gunicorn; extra == "http"
69
70
  Requires-Dist: httpcore; extra == "http"
70
71
  Requires-Dist: httpx; extra == "http"
72
+ Requires-Dist: langfuse; extra == "http"
71
73
  Requires-Dist: python-socketio; extra == "http"
72
74
 
73
75
  ## Introduction
@@ -8,6 +8,7 @@ sunholo/logging.py
8
8
  sunholo.egg-info/PKG-INFO
9
9
  sunholo.egg-info/SOURCES.txt
10
10
  sunholo.egg-info/dependency_links.txt
11
+ sunholo.egg-info/entry_points.txt
11
12
  sunholo.egg-info/requires.txt
12
13
  sunholo.egg-info/top_level.txt
13
14
  sunholo/agents/__init__.py
@@ -40,6 +41,8 @@ sunholo/chunker/message_data.py
40
41
  sunholo/chunker/pdfs.py
41
42
  sunholo/chunker/publish.py
42
43
  sunholo/chunker/splitter.py
44
+ sunholo/cli/__init__.py
45
+ sunholo/cli/cli.py
43
46
  sunholo/components/__init__.py
44
47
  sunholo/components/llm.py
45
48
  sunholo/components/prompt.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ sunholo = sunholo.cli.cli:main
@@ -11,6 +11,7 @@ google-cloud-alloydb-connector[pg8000]
11
11
  google-cloud-logging
12
12
  google-cloud-storage
13
13
  google-cloud-pubsub
14
+ gunicorn
14
15
  httpcore
15
16
  httpx
16
17
  lancedb
@@ -46,11 +47,12 @@ google-api-python-client
46
47
  google-cloud-alloydb-connector[pg8000]
47
48
 
48
49
  [http]
49
- langfuse
50
50
  fastapi
51
51
  flask
52
+ gunicorn
52
53
  httpcore
53
54
  httpx
55
+ langfuse
54
56
  python-socketio
55
57
 
56
58
  [openai]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes