sunholo 0.77.1__tar.gz → 0.77.3__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 (147) hide show
  1. {sunholo-0.77.1 → sunholo-0.77.3}/PKG-INFO +4 -2
  2. {sunholo-0.77.1 → sunholo-0.77.3}/setup.py +3 -1
  3. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/flask/qna_routes.py +4 -2
  4. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/auth/run.py +13 -9
  5. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/components/llm.py +19 -10
  6. sunholo-0.77.3/sunholo/invoke/__init__.py +2 -0
  7. sunholo-0.77.3/sunholo/invoke/direct_vac_func.py +129 -0
  8. sunholo-0.77.3/sunholo/invoke/invoke_vac_utils.py +59 -0
  9. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/extensions_call.py +1 -1
  10. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo.egg-info/PKG-INFO +4 -2
  11. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo.egg-info/SOURCES.txt +1 -0
  12. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo.egg-info/requires.txt +2 -0
  13. sunholo-0.77.1/sunholo/invoke/__init__.py +0 -1
  14. sunholo-0.77.1/sunholo/invoke/invoke_vac_utils.py +0 -151
  15. {sunholo-0.77.1 → sunholo-0.77.3}/LICENSE.txt +0 -0
  16. {sunholo-0.77.1 → sunholo-0.77.3}/MANIFEST.in +0 -0
  17. {sunholo-0.77.1 → sunholo-0.77.3}/README.md +0 -0
  18. {sunholo-0.77.1 → sunholo-0.77.3}/setup.cfg +0 -0
  19. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/__init__.py +0 -0
  20. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/__init__.py +0 -0
  21. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/chat_history.py +0 -0
  22. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/dispatch_to_qa.py +0 -0
  23. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/fastapi/__init__.py +0 -0
  24. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/fastapi/base.py +0 -0
  25. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/fastapi/qna_routes.py +0 -0
  26. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/flask/__init__.py +0 -0
  27. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/flask/base.py +0 -0
  28. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/flask/vac_routes.py +0 -0
  29. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/langserve.py +0 -0
  30. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/pubsub.py +0 -0
  31. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/route.py +0 -0
  32. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/special_commands.py +0 -0
  33. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/agents/swagger.py +0 -0
  34. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/archive/__init__.py +0 -0
  35. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/archive/archive.py +0 -0
  36. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/auth/__init__.py +0 -0
  37. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/auth/gcloud.py +0 -0
  38. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/auth/refresh.py +0 -0
  39. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/azure/__init__.py +0 -0
  40. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/azure/event_grid.py +0 -0
  41. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/bots/__init__.py +0 -0
  42. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/bots/discord.py +0 -0
  43. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/bots/github_webhook.py +0 -0
  44. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/bots/webapp.py +0 -0
  45. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/__init__.py +0 -0
  46. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/azure.py +0 -0
  47. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/doc_handling.py +0 -0
  48. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/images.py +0 -0
  49. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/loaders.py +0 -0
  50. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/message_data.py +0 -0
  51. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/pdfs.py +0 -0
  52. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/process_chunker_data.py +0 -0
  53. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/publish.py +0 -0
  54. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/pubsub.py +0 -0
  55. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/chunker/splitter.py +0 -0
  56. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/__init__.py +0 -0
  57. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/chat_vac.py +0 -0
  58. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/cli.py +0 -0
  59. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/cli_init.py +0 -0
  60. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/configs.py +0 -0
  61. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/deploy.py +0 -0
  62. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/embedder.py +0 -0
  63. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/merge_texts.py +0 -0
  64. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/run_proxy.py +0 -0
  65. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/sun_rich.py +0 -0
  66. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/swagger.py +0 -0
  67. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/cli/vertex.py +0 -0
  68. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/components/__init__.py +0 -0
  69. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/components/retriever.py +0 -0
  70. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/components/vectorstore.py +0 -0
  71. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/__init__.py +0 -0
  72. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/alloydb.py +0 -0
  73. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/alloydb_client.py +0 -0
  74. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/database.py +0 -0
  75. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/lancedb.py +0 -0
  76. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/sql/sb/create_function.sql +0 -0
  77. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/sql/sb/create_function_time.sql +0 -0
  78. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/sql/sb/create_table.sql +0 -0
  79. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  80. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/sql/sb/return_sources.sql +0 -0
  81. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/sql/sb/setup.sql +0 -0
  82. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/static_dbs.py +0 -0
  83. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/database/uuid.py +0 -0
  84. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/discovery_engine/__init__.py +0 -0
  85. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/discovery_engine/chunker_handler.py +0 -0
  86. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/discovery_engine/create_new.py +0 -0
  87. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  88. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/embedder/__init__.py +0 -0
  89. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/embedder/embed_chunk.py +0 -0
  90. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/gcs/__init__.py +0 -0
  91. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/gcs/add_file.py +0 -0
  92. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/gcs/download_folder.py +0 -0
  93. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/gcs/download_url.py +0 -0
  94. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/gcs/metadata.py +0 -0
  95. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/langfuse/__init__.py +0 -0
  96. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/langfuse/callback.py +0 -0
  97. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/langfuse/prompts.py +0 -0
  98. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/llamaindex/__init__.py +0 -0
  99. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/llamaindex/generate.py +0 -0
  100. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/llamaindex/get_files.py +0 -0
  101. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/llamaindex/import_files.py +0 -0
  102. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/logging.py +0 -0
  103. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/lookup/__init__.py +0 -0
  104. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/lookup/model_lookup.yaml +0 -0
  105. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/patches/__init__.py +0 -0
  106. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/patches/langchain/__init__.py +0 -0
  107. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/patches/langchain/lancedb.py +0 -0
  108. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/patches/langchain/vertexai.py +0 -0
  109. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/pubsub/__init__.py +0 -0
  110. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/pubsub/process_pubsub.py +0 -0
  111. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/pubsub/pubsub_manager.py +0 -0
  112. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/qna/__init__.py +0 -0
  113. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/qna/parsers.py +0 -0
  114. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/qna/retry.py +0 -0
  115. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/streaming/__init__.py +0 -0
  116. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/streaming/content_buffer.py +0 -0
  117. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/streaming/langserve.py +0 -0
  118. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/streaming/stream_lookup.py +0 -0
  119. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/streaming/streaming.py +0 -0
  120. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/summarise/__init__.py +0 -0
  121. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/summarise/summarise.py +0 -0
  122. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/tools/__init__.py +0 -0
  123. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/tools/web_browser.py +0 -0
  124. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/__init__.py +0 -0
  125. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/api_key.py +0 -0
  126. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/big_context.py +0 -0
  127. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/config.py +0 -0
  128. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/config_class.py +0 -0
  129. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/config_schema.py +0 -0
  130. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/gcp.py +0 -0
  131. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/gcp_project.py +0 -0
  132. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/parsers.py +0 -0
  133. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/timedelta.py +0 -0
  134. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/user_ids.py +0 -0
  135. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/utils/version.py +0 -0
  136. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/__init__.py +0 -0
  137. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/extensions_class.py +0 -0
  138. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/genai_functions.py +0 -0
  139. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/init.py +0 -0
  140. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/memory_tools.py +0 -0
  141. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/safety.py +0 -0
  142. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo/vertex/type_dict_to_json.py +0 -0
  143. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo.egg-info/dependency_links.txt +0 -0
  144. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo.egg-info/entry_points.txt +0 -0
  145. {sunholo-0.77.1 → sunholo-0.77.3}/sunholo.egg-info/top_level.txt +0 -0
  146. {sunholo-0.77.1 → sunholo-0.77.3}/tests/test_chat_history.py +0 -0
  147. {sunholo-0.77.1 → sunholo-0.77.3}/tests/test_config.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.77.1
3
+ Version: 0.77.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.77.1.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.77.3.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -54,6 +54,7 @@ Requires-Dist: langchain-openai; extra == "all"
54
54
  Requires-Dist: langchain-google-genai; extra == "all"
55
55
  Requires-Dist: langchain_google_alloydb_pg; extra == "all"
56
56
  Requires-Dist: langchain-anthropic>=0.1.13; extra == "all"
57
+ Requires-Dist: langchain-google-vertexai; extra == "all"
57
58
  Requires-Dist: langfuse; extra == "all"
58
59
  Requires-Dist: pg8000; extra == "all"
59
60
  Requires-Dist: pgvector; extra == "all"
@@ -108,6 +109,7 @@ Requires-Dist: google-cloud-discoveryengine; extra == "gcp"
108
109
  Requires-Dist: google-generativeai>=0.7.1; extra == "gcp"
109
110
  Requires-Dist: langchain-google-genai>=1.0.5; extra == "gcp"
110
111
  Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
112
+ Requires-Dist: langchain-google-vertexai; extra == "gcp"
111
113
  Requires-Dist: pillow; extra == "gcp"
112
114
  Provides-Extra: openai
113
115
  Requires-Dist: langchain-openai; extra == "openai"
@@ -1,7 +1,7 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
3
  # Define your base version
4
- version = '0.77.1'
4
+ version = '0.77.3'
5
5
 
6
6
  setup(
7
7
  name='sunholo',
@@ -69,6 +69,7 @@ setup(
69
69
  "langchain-google-genai",
70
70
  "langchain_google_alloydb_pg",
71
71
  "langchain-anthropic>=0.1.13",
72
+ "langchain-google-vertexai",
72
73
  "langfuse",
73
74
  "pg8000",
74
75
  "pgvector",
@@ -129,6 +130,7 @@ setup(
129
130
  "google-generativeai>=0.7.1",
130
131
  "langchain-google-genai>=1.0.5",
131
132
  "langchain_google_alloydb_pg>=0.2.2",
133
+ "langchain-google-vertexai",
132
134
  "pillow",
133
135
 
134
136
  ],
@@ -522,9 +522,11 @@ def prep_vac(request, vector_name):
522
522
  config, _ = load_config("config/llm_config.yaml")
523
523
  vac_configs = config.get("vac")
524
524
  if vac_configs:
525
- vac_config = vac_configs[vector_name]
525
+ vac_config = vac_configs.get(vector_name)
526
+ if not vac_config:
527
+ log.warning("Not a local configured VAC, may be a remote config not synced yet")
526
528
 
527
- if trace:
529
+ if trace and vac_config:
528
530
  trace.update(input=data, metadata=vac_config)
529
531
 
530
532
  user_input = data.pop('user_input').strip()
@@ -2,22 +2,23 @@
2
2
  import inspect
3
3
 
4
4
  from typing import Dict, Optional
5
- from ..utils.config import load_config_key, load_config
5
+ from ..utils.config import load_config
6
+ from ..utils import ConfigManager
6
7
  from ..utils.gcp import is_running_on_cloudrun
7
8
  from ..utils.api_key import has_multivac_api_key, get_multivac_api_key
8
9
  from ..logging import log
9
10
  from ..agents.route import route_vac
10
11
  from .gcloud import get_local_gcloud_token
11
12
 
12
- def get_run_url(vector_name=None):
13
+ def get_run_url(config):
13
14
 
14
- if not vector_name:
15
+ if not config:
15
16
  raise ValueError('Vector name was not specified')
16
17
 
17
- cloud_urls = route_vac(vector_name)
18
+ cloud_urls = route_vac(config=config)
18
19
 
19
20
  cloud_urls, _ = load_config('config/cloud_run_urls.json')
20
- agent = load_config_key("agent", vector_name=vector_name, kind="vacConfig")
21
+ agent = config.vacConfig("agent")
21
22
 
22
23
  try:
23
24
  log.info(f'Looking up URL for {agent}')
@@ -44,10 +45,13 @@ def get_cloud_run_token(vector_name):
44
45
 
45
46
  return {"x-api-key": get_multivac_api_key()}
46
47
 
47
- if is_running_on_cloudrun():
48
- run_url = get_run_url(vector_name)
49
- else:
50
- run_url = "http://127.0.0.1:8080"
48
+ #if is_running_on_cloudrun():
49
+ # run_url = get_run_url(vector_name)
50
+ #else:
51
+ # run_url = "http://127.0.0.1:8080"
52
+
53
+ config = ConfigManager(vector_name)
54
+ run_url = get_run_url(config)
51
55
 
52
56
  # Append ID Token to make authenticated requests to Cloud Run services
53
57
  frame = inspect.currentframe()
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  from ..logging import log
15
- from ..utils.config import load_config_key
15
+ from ..utils import load_config_key, ConfigManager
16
16
 
17
17
  import os
18
18
 
@@ -57,7 +57,14 @@ 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):
60
+ def llm_str_to_llm(llm_str, model=None, vector_name=None, config=None):
61
+
62
+ if llm_str is None:
63
+ raise NotImplementedError("llm_str was None")
64
+
65
+ if vector_name:
66
+ config = ConfigManager(vector_name)
67
+
61
68
  if llm_str == 'openai':
62
69
  # Setup for OpenAI LLM
63
70
  from langchain_openai import ChatOpenAI
@@ -70,7 +77,7 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None):
70
77
 
71
78
  elif llm_str == 'vertex':
72
79
  # Setup for Vertex LLM
73
- from langchain_community.llms import VertexAI
80
+ from langchain_google_vertexai import VertexAI
74
81
  if model is None:
75
82
  model = 'text-unicorn'
76
83
  log.info(f"No 'model' value in config file - selecting default {model}")
@@ -79,7 +86,7 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None):
79
86
 
80
87
  elif llm_str == 'model_garden':
81
88
  from ..patches.langchain.vertexai import VertexAIModelGarden
82
- model_garden_config = load_config_key("gcp_config", vector_name, kind="vacConfig")
89
+ model_garden_config = config.vacConfig("gcp_config")
83
90
  if model_garden_config is None:
84
91
  raise ValueError("llm='model_garden' requires a gcp_config entry in config yaml file")
85
92
 
@@ -97,16 +104,18 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None):
97
104
  if llm_str is None:
98
105
  raise NotImplementedError(f'No llm implemented for {llm_str}')
99
106
 
100
- def get_llm(vector_name, model=None):
101
- llm_str = load_config_key("llm", vector_name, kind="vacConfig")
102
- #model_lookup_filepath = get_module_filepath("lookup/model_lookup.yaml")
103
- #model_lookup, _ = load_config(model_lookup_filepath)
107
+ def get_llm(vector_name=None, model=None, config=None):
108
+
109
+ if vector_name:
110
+ config = ConfigManager(vector_name)
111
+
112
+ llm_str = config.vacConfig("llm")
104
113
 
105
114
  if not model:
106
- model = load_config_key("model", vector_name, kind="vacConfig")
115
+ model = config.vacConfig("model")
107
116
 
108
117
  log.debug(f"Chose LLM: {llm_str}")
109
- return llm_str_to_llm(llm_str, model=model, vector_name=vector_name)
118
+ return llm_str_to_llm(llm_str, model=model, config=config)
110
119
 
111
120
  def get_llm_chat(vector_name, model=None):
112
121
  llm_str = load_config_key("llm", vector_name, kind="vacConfig")
@@ -0,0 +1,2 @@
1
+ from .invoke_vac_utils import invoke_vac
2
+ from .direct_vac_func import direct_vac, direct_vac_stream
@@ -0,0 +1,129 @@
1
+ from ..logging import log
2
+ from ..agents import send_to_qa
3
+ from ..qna.parsers import parse_output
4
+ from ..streaming import generate_proxy_stream
5
+ from ..utils import ConfigManager
6
+ from ..utils.api_key import has_multivac_api_key
7
+
8
+ def direct_vac(vac_input: dict, vac_name: str, chat_history=[]):
9
+ """
10
+ This lets VACs call other VAC Q&A endpoints within their code
11
+ """
12
+
13
+ log.info(f"Invoking VAC Q&A endpoints for {vac_name}")
14
+
15
+ if 'user_input' not in vac_input:
16
+ raise ValueError('vac_input must contain at least "user_input" key - got {vac_input}')
17
+
18
+ user_id = vac_input.get('user_id')
19
+ session_id = vac_input.get('session_id')
20
+ image_uri = vac_input.get('image_url') or vac_input.get('image_uri')
21
+
22
+ global_config = ConfigManager('global')
23
+ config = ConfigManager(vac_name)
24
+
25
+ agent_name = config.vacConfig('agent')
26
+ agent_url = config.vacConfig("agent_url")
27
+
28
+ if agent_url:
29
+ log.info("Found agent_url within vacConfig: {agent_url}")
30
+ # via public cloud endpoints - assumes no gcloud auth
31
+ override_endpoint = None
32
+ if has_multivac_api_key():
33
+ print("Found MULTIVAC_API_KEY")
34
+ gcp_config = global_config.vacConfig("gcp_config")
35
+ endpoints_base_url = gcp_config.get("endpoints_base_url")
36
+ if not endpoints_base_url:
37
+ raise ValueError("MULTIVAC_API_KEY env var is set but no config.gcp_config.endpoints_base_url can be found")
38
+
39
+ override_endpoint = f"{endpoints_base_url}/v1/{agent_name}"
40
+
41
+ override_endpoint = agent_url or override_endpoint
42
+
43
+ print(f"Using {override_endpoint=}")
44
+ log.warning(f'Batch invoke_vac_qa with {vac_input=}')
45
+ vac_response = send_to_qa(
46
+ vac_input["user_input"],
47
+ vector_name=vac_name,
48
+ chat_history=chat_history,
49
+ message_author=user_id,
50
+ #TODO: populate these
51
+ image_url=image_uri,
52
+ source_filters=None,
53
+ search_kwargs=None,
54
+ private_docs=None,
55
+ whole_document=False,
56
+ source_filters_and_or=False,
57
+ # system kwargs
58
+ configurable={
59
+ "vector_name": vac_name,
60
+ },
61
+ user_id=user_id,
62
+ session_id=session_id,
63
+ message_source="sunholo.invoke_vac_qa.invoke",
64
+ override_endpoint=override_endpoint,
65
+ stream=False)
66
+
67
+ # ensures {'answer': answer}
68
+ answer = parse_output(vac_response)
69
+ chat_history.append({"name": "Human", "content": vac_input})
70
+ chat_history.append({"name": "AI", "content": answer})
71
+ answer["chat_history"] = chat_history
72
+
73
+ return answer
74
+
75
+ def direct_vac_stream(vac_input: dict, vac_name: str, chat_history=[]):
76
+
77
+ if 'user_input' not in vac_input:
78
+ raise ValueError('vac_input must contain at least "user_input" key - got {vac_input}')
79
+
80
+ user_id = vac_input.get('user_id')
81
+ session_id = vac_input.get('session_id')
82
+ image_uri = vac_input.get('image_url') or vac_input.get('image_uri')
83
+
84
+ log.info(f"Streaming invoke_vac_qa with {vac_input=}")
85
+ def stream_response():
86
+ generate = generate_proxy_stream(
87
+ send_to_qa,
88
+ vac_input["user_input"],
89
+ vector_name=vac_name,
90
+ chat_history=chat_history,
91
+ generate_f_output=lambda x: x, # Replace with actual processing function
92
+ stream_wait_time=0.5,
93
+ stream_timeout=120,
94
+ message_author=user_id,
95
+ #TODO: populate these
96
+ image_url=image_uri,
97
+ source_filters=None,
98
+ search_kwargs=None,
99
+ private_docs=None,
100
+ whole_document=False,
101
+ source_filters_and_or=False,
102
+ # system kwargs
103
+ configurable={
104
+ "vector_name": vac_name,
105
+ },
106
+ user_id=user_id,
107
+ session_id=session_id,
108
+ message_source="sunholo.invoke_vac_qa.stream"
109
+ )
110
+ for part in generate():
111
+ yield part
112
+
113
+ answer = ""
114
+
115
+ for token in stream_response():
116
+ if isinstance(token, bytes):
117
+ token = token.decode('utf-8')
118
+ yield token
119
+ if isinstance(token, dict):
120
+ # ?
121
+ pass
122
+ elif isinstance(token, str):
123
+ answer += token
124
+
125
+ if answer:
126
+ chat_history.append({"name": "Human", "content": vac_input})
127
+ chat_history.append({"name": "AI", "content": answer})
128
+
129
+ return chat_history
@@ -0,0 +1,59 @@
1
+ import json
2
+ import requests
3
+
4
+ from pathlib import Path
5
+
6
+ from ..logging import log
7
+
8
+ def invoke_vac(service_url, data, vector_name=None, metadata=None, is_file=False):
9
+ """
10
+ This lets a VAC be invoked by directly calling its URL, used for file uploads
11
+ """
12
+ try:
13
+ if is_file:
14
+ log.info("Uploading file...")
15
+ # Handle file upload
16
+ if not isinstance(data, Path) or not data.is_file():
17
+ raise ValueError("For file uploads, 'data' must be a Path object pointing to a valid file.")
18
+
19
+ files = {
20
+ 'file': (data.name, open(data, 'rb')),
21
+ }
22
+ form_data = {
23
+ 'vector_name': vector_name,
24
+ 'metadata': json.dumps(metadata) if metadata else '',
25
+ }
26
+
27
+ response = requests.post(service_url, files=files, data=form_data)
28
+ else:
29
+ log.info("Uploading JSON...")
30
+ try:
31
+ if isinstance(data, dict):
32
+ json_data = data
33
+ else:
34
+ json_data = json.loads(data)
35
+ except json.JSONDecodeError as err:
36
+ log.error(f"[bold red]ERROR: invalid JSON: {str(err)} [/bold red]")
37
+ raise err
38
+ except Exception as err:
39
+ log.error(f"[bold red]ERROR: could not parse JSON: {str(err)} [/bold red]")
40
+ raise err
41
+
42
+ log.debug(f"Sending data: {data} or json_data: {json.dumps(json_data)}")
43
+ # Handle JSON data
44
+ headers = {"Content-Type": "application/json"}
45
+ response = requests.post(service_url, headers=headers, data=json.dumps(json_data))
46
+
47
+ response.raise_for_status()
48
+
49
+ the_data = response.json()
50
+ log.info(the_data)
51
+
52
+ return the_data
53
+
54
+ except requests.exceptions.RequestException as e:
55
+ log.error(f"[bold red]ERROR: Failed to invoke VAC: {e}[/bold red]")
56
+ raise e
57
+ except Exception as e:
58
+ log.error(f"[bold red]ERROR: An unexpected error occurred: {e}[/bold red]")
59
+ raise e
@@ -10,7 +10,7 @@ def dynamic_extension_call(question, config:ConfigManager, project_id:str=None,
10
10
 
11
11
  extensions = config.vacConfig('extensions')
12
12
  if not extensions:
13
- log.warning("No extensions founded for vac: {vac}")
13
+ log.warning(f"No extensions founded for vac: {ConfigManager.vector_name}")
14
14
 
15
15
  return None
16
16
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.77.1
3
+ Version: 0.77.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.77.1.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.77.3.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -54,6 +54,7 @@ Requires-Dist: langchain-openai; extra == "all"
54
54
  Requires-Dist: langchain-google-genai; extra == "all"
55
55
  Requires-Dist: langchain_google_alloydb_pg; extra == "all"
56
56
  Requires-Dist: langchain-anthropic>=0.1.13; extra == "all"
57
+ Requires-Dist: langchain-google-vertexai; extra == "all"
57
58
  Requires-Dist: langfuse; extra == "all"
58
59
  Requires-Dist: pg8000; extra == "all"
59
60
  Requires-Dist: pgvector; extra == "all"
@@ -108,6 +109,7 @@ Requires-Dist: google-cloud-discoveryengine; extra == "gcp"
108
109
  Requires-Dist: google-generativeai>=0.7.1; extra == "gcp"
109
110
  Requires-Dist: langchain-google-genai>=1.0.5; extra == "gcp"
110
111
  Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
112
+ Requires-Dist: langchain-google-vertexai; extra == "gcp"
111
113
  Requires-Dist: pillow; extra == "gcp"
112
114
  Provides-Extra: openai
113
115
  Requires-Dist: langchain-openai; extra == "openai"
@@ -90,6 +90,7 @@ sunholo/gcs/download_folder.py
90
90
  sunholo/gcs/download_url.py
91
91
  sunholo/gcs/metadata.py
92
92
  sunholo/invoke/__init__.py
93
+ sunholo/invoke/direct_vac_func.py
93
94
  sunholo/invoke/invoke_vac_utils.py
94
95
  sunholo/langfuse/__init__.py
95
96
  sunholo/langfuse/callback.py
@@ -35,6 +35,7 @@ langchain-openai
35
35
  langchain-google-genai
36
36
  langchain_google_alloydb_pg
37
37
  langchain-anthropic>=0.1.13
38
+ langchain-google-vertexai
38
39
  langfuse
39
40
  pg8000
40
41
  pgvector
@@ -88,6 +89,7 @@ google-cloud-discoveryengine
88
89
  google-generativeai>=0.7.1
89
90
  langchain-google-genai>=1.0.5
90
91
  langchain_google_alloydb_pg>=0.2.2
92
+ langchain-google-vertexai
91
93
  pillow
92
94
 
93
95
  [http]
@@ -1 +0,0 @@
1
- from .invoke_vac_utils import invoke_vac, invoke_vac_qa
@@ -1,151 +0,0 @@
1
- import json
2
- import requests
3
-
4
- from pathlib import Path
5
-
6
- from ..logging import log
7
- from ..agents import send_to_qa
8
- from ..qna.parsers import parse_output
9
- from ..streaming import generate_proxy_stream
10
-
11
- def invoke_vac_qa(vac_input: dict, vac_name: str, chat_history=[], stream=False):
12
- """
13
- This lets VACs call other VAC Q&A endpoints within their code
14
- """
15
-
16
- if 'user_input' not in vac_input:
17
- raise ValueError('vac_input must contain at least "user_input" key - got {vac_input}')
18
-
19
- user_id = vac_input.get('user_id')
20
- session_id = vac_input.get('session_id')
21
- image_uri = vac_input.get('image_url') or vac_input.get('image_uri')
22
-
23
- if not stream:
24
- log.info(f'Batch invoke_vac_qa with {vac_input=}')
25
- vac_response = send_to_qa(
26
- vac_input["user_input"],
27
- vector_name=vac_name,
28
- chat_history=chat_history,
29
- message_author=user_id,
30
- #TODO: populate these
31
- image_url=image_uri,
32
- source_filters=None,
33
- search_kwargs=None,
34
- private_docs=None,
35
- whole_document=False,
36
- source_filters_and_or=False,
37
- # system kwargs
38
- configurable={
39
- "vector_name": vac_name,
40
- },
41
- user_id=user_id,
42
- session_id=session_id,
43
- message_source="sunholo.invoke_vac_qa.invoke")
44
-
45
- # ensures {'answer': answer}
46
- answer = parse_output(vac_response)
47
- chat_history.append({"name": "Human", "content": vac_input})
48
- chat_history.append({"name": "AI", "content": answer})
49
- answer["chat_history"] = chat_history
50
-
51
- return answer
52
-
53
- log.info(f"Streaming invoke_vac_qa with {vac_input=}")
54
- def stream_response():
55
- generate = generate_proxy_stream(
56
- send_to_qa,
57
- vac_input["user_input"],
58
- vector_name=vac_name,
59
- chat_history=chat_history,
60
- generate_f_output=lambda x: x, # Replace with actual processing function
61
- stream_wait_time=0.5,
62
- stream_timeout=120,
63
- message_author=user_id,
64
- #TODO: populate these
65
- image_url=image_uri,
66
- source_filters=None,
67
- search_kwargs=None,
68
- private_docs=None,
69
- whole_document=False,
70
- source_filters_and_or=False,
71
- # system kwargs
72
- configurable={
73
- "vector_name": vac_name,
74
- },
75
- user_id=user_id,
76
- session_id=session_id,
77
- message_source="sunholo.invoke_vac_qa.stream"
78
- )
79
- for part in generate():
80
- yield part
81
-
82
- answer = ""
83
-
84
- for token in stream_response():
85
- if isinstance(token, bytes):
86
- token = token.decode('utf-8')
87
- yield token
88
- if isinstance(token, dict):
89
- # ?
90
- pass
91
- elif isinstance(token, str):
92
- answer += token
93
-
94
- if answer:
95
- chat_history.append({"name": "Human", "content": vac_input})
96
- chat_history.append({"name": "AI", "content": answer})
97
-
98
- return chat_history
99
-
100
- def invoke_vac(service_url, data, vector_name=None, metadata=None, is_file=False):
101
- """
102
- This lets a VAC be invoked by directly calling its URL, used for file uploads
103
- """
104
- try:
105
- if is_file:
106
- log.info("Uploading file...")
107
- # Handle file upload
108
- if not isinstance(data, Path) or not data.is_file():
109
- raise ValueError("For file uploads, 'data' must be a Path object pointing to a valid file.")
110
-
111
- files = {
112
- 'file': (data.name, open(data, 'rb')),
113
- }
114
- form_data = {
115
- 'vector_name': vector_name,
116
- 'metadata': json.dumps(metadata) if metadata else '',
117
- }
118
-
119
- response = requests.post(service_url, files=files, data=form_data)
120
- else:
121
- log.info("Uploading JSON...")
122
- try:
123
- if isinstance(data, dict):
124
- json_data = data
125
- else:
126
- json_data = json.loads(data)
127
- except json.JSONDecodeError as err:
128
- log.error(f"[bold red]ERROR: invalid JSON: {str(err)} [/bold red]")
129
- raise err
130
- except Exception as err:
131
- log.error(f"[bold red]ERROR: could not parse JSON: {str(err)} [/bold red]")
132
- raise err
133
-
134
- log.debug(f"Sending data: {data} or json_data: {json.dumps(json_data)}")
135
- # Handle JSON data
136
- headers = {"Content-Type": "application/json"}
137
- response = requests.post(service_url, headers=headers, data=json.dumps(json_data))
138
-
139
- response.raise_for_status()
140
-
141
- the_data = response.json()
142
- log.info(the_data)
143
-
144
- return the_data
145
-
146
- except requests.exceptions.RequestException as e:
147
- log.error(f"[bold red]ERROR: Failed to invoke VAC: {e}[/bold red]")
148
- raise e
149
- except Exception as e:
150
- log.error(f"[bold red]ERROR: An unexpected error occurred: {e}[/bold red]")
151
- raise e
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes