sunholo 0.86.1__tar.gz → 0.88.0__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 (159) hide show
  1. {sunholo-0.86.1 → sunholo-0.88.0}/PKG-INFO +5 -2
  2. {sunholo-0.86.1 → sunholo-0.88.0}/setup.py +5 -3
  3. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/__init__.py +2 -0
  4. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/vac_routes.py +46 -2
  5. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/cli.py +11 -8
  6. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/add_file.py +3 -0
  7. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/process_funcs_cls.py +5 -1
  8. sunholo-0.88.0/sunholo/terraform/__init__.py +1 -0
  9. sunholo-0.88.0/sunholo/terraform/tfvars_editor.py +270 -0
  10. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/PKG-INFO +5 -2
  11. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/SOURCES.txt +2 -0
  12. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/requires.txt +4 -0
  13. {sunholo-0.86.1 → sunholo-0.88.0}/LICENSE.txt +0 -0
  14. {sunholo-0.86.1 → sunholo-0.88.0}/MANIFEST.in +0 -0
  15. {sunholo-0.86.1 → sunholo-0.88.0}/README.md +0 -0
  16. {sunholo-0.86.1 → sunholo-0.88.0}/setup.cfg +0 -0
  17. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/__init__.py +0 -0
  18. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/chat_history.py +0 -0
  19. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/dispatch_to_qa.py +0 -0
  20. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/fastapi/__init__.py +0 -0
  21. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/fastapi/base.py +0 -0
  22. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/fastapi/qna_routes.py +0 -0
  23. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/__init__.py +0 -0
  24. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/base.py +0 -0
  25. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/qna_routes.py +0 -0
  26. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/langserve.py +0 -0
  27. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/pubsub.py +0 -0
  28. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/route.py +0 -0
  29. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/special_commands.py +0 -0
  30. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/swagger.py +0 -0
  31. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/archive/__init__.py +0 -0
  32. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/archive/archive.py +0 -0
  33. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/__init__.py +0 -0
  34. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/gcloud.py +0 -0
  35. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/refresh.py +0 -0
  36. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/run.py +0 -0
  37. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/__init__.py +0 -0
  38. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/auth.py +0 -0
  39. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/blobs.py +0 -0
  40. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/event_grid.py +0 -0
  41. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/__init__.py +0 -0
  42. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/discord.py +0 -0
  43. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/github_webhook.py +0 -0
  44. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/webapp.py +0 -0
  45. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/__init__.py +0 -0
  46. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/azure.py +0 -0
  47. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/doc_handling.py +0 -0
  48. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/encode_metadata.py +0 -0
  49. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/images.py +0 -0
  50. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/loaders.py +0 -0
  51. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/message_data.py +0 -0
  52. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/pdfs.py +0 -0
  53. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/process_chunker_data.py +0 -0
  54. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/publish.py +0 -0
  55. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/pubsub.py +0 -0
  56. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/splitter.py +0 -0
  57. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/__init__.py +0 -0
  58. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/chat_vac.py +0 -0
  59. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/cli_init.py +0 -0
  60. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/configs.py +0 -0
  61. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/deploy.py +0 -0
  62. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/embedder.py +0 -0
  63. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/merge_texts.py +0 -0
  64. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/run_proxy.py +0 -0
  65. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/sun_rich.py +0 -0
  66. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/swagger.py +0 -0
  67. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/vertex.py +0 -0
  68. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/__init__.py +0 -0
  69. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/llm.py +0 -0
  70. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/retriever.py +0 -0
  71. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/vectorstore.py +0 -0
  72. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/custom_logging.py +0 -0
  73. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/__init__.py +0 -0
  74. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/alloydb.py +0 -0
  75. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/alloydb_client.py +0 -0
  76. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/database.py +0 -0
  77. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/lancedb.py +0 -0
  78. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/create_function.sql +0 -0
  79. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/create_function_time.sql +0 -0
  80. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/create_table.sql +0 -0
  81. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  82. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/return_sources.sql +0 -0
  83. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/setup.sql +0 -0
  84. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/static_dbs.py +0 -0
  85. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/uuid.py +0 -0
  86. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/__init__.py +0 -0
  87. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/chunker_handler.py +0 -0
  88. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/create_new.py +0 -0
  89. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  90. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  91. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/embedder/__init__.py +0 -0
  92. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/embedder/embed_chunk.py +0 -0
  93. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/excel/__init__.py +0 -0
  94. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/excel/plugin.py +0 -0
  95. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/__init__.py +0 -0
  96. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/download_folder.py +0 -0
  97. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/download_url.py +0 -0
  98. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/metadata.py +0 -0
  99. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/__init__.py +0 -0
  100. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/init.py +0 -0
  101. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/safety.py +0 -0
  102. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/__init__.py +0 -0
  103. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/async_class.py +0 -0
  104. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/direct_vac_func.py +0 -0
  105. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/invoke_vac_utils.py +0 -0
  106. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/langfuse/__init__.py +0 -0
  107. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/langfuse/callback.py +0 -0
  108. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/langfuse/prompts.py +0 -0
  109. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/__init__.py +0 -0
  110. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/get_files.py +0 -0
  111. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/import_files.py +0 -0
  112. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/llamaindex_class.py +0 -0
  113. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/user_history.py +0 -0
  114. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/lookup/__init__.py +0 -0
  115. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/lookup/model_lookup.yaml +0 -0
  116. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/__init__.py +0 -0
  117. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/langchain/__init__.py +0 -0
  118. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/langchain/lancedb.py +0 -0
  119. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/langchain/vertexai.py +0 -0
  120. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/pubsub/__init__.py +0 -0
  121. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/pubsub/process_pubsub.py +0 -0
  122. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/pubsub/pubsub_manager.py +0 -0
  123. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/qna/__init__.py +0 -0
  124. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/qna/parsers.py +0 -0
  125. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/qna/retry.py +0 -0
  126. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/__init__.py +0 -0
  127. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/content_buffer.py +0 -0
  128. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/langserve.py +0 -0
  129. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/stream_lookup.py +0 -0
  130. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/streaming.py +0 -0
  131. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/summarise/__init__.py +0 -0
  132. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/summarise/summarise.py +0 -0
  133. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/tools/__init__.py +0 -0
  134. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/tools/web_browser.py +0 -0
  135. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/__init__.py +0 -0
  136. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/api_key.py +0 -0
  137. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/big_context.py +0 -0
  138. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/config.py +0 -0
  139. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/config_class.py +0 -0
  140. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/config_schema.py +0 -0
  141. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/gcp.py +0 -0
  142. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/gcp_project.py +0 -0
  143. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/parsers.py +0 -0
  144. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/timedelta.py +0 -0
  145. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/user_ids.py +0 -0
  146. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/version.py +0 -0
  147. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/__init__.py +0 -0
  148. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/extensions_call.py +0 -0
  149. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/extensions_class.py +0 -0
  150. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/genai_functions.py +0 -0
  151. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/init.py +0 -0
  152. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/memory_tools.py +0 -0
  153. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/safety.py +0 -0
  154. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/type_dict_to_json.py +0 -0
  155. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/dependency_links.txt +0 -0
  156. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/entry_points.txt +0 -0
  157. {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/top_level.txt +0 -0
  158. {sunholo-0.86.1 → sunholo-0.88.0}/tests/test_chat_history.py +0 -0
  159. {sunholo-0.86.1 → sunholo-0.88.0}/tests/test_config.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.86.1
3
+ Version: 0.88.0
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.86.1.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.88.0.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -64,6 +64,7 @@ Requires-Dist: playwright; extra == "all"
64
64
  Requires-Dist: psutil; extra == "all"
65
65
  Requires-Dist: psycopg2-binary; extra == "all"
66
66
  Requires-Dist: pypdf; extra == "all"
67
+ Requires-Dist: python-hcl2; extra == "all"
67
68
  Requires-Dist: python-socketio; extra == "all"
68
69
  Requires-Dist: pytesseract; extra == "all"
69
70
  Requires-Dist: rich; extra == "all"
@@ -135,6 +136,8 @@ Provides-Extra: excel
135
136
  Requires-Dist: xlwings; extra == "excel"
136
137
  Requires-Dist: requests; extra == "excel"
137
138
  Requires-Dist: rich; extra == "excel"
139
+ Provides-Extra: iac
140
+ Requires-Dist: python-hcl2; extra == "iac"
138
141
 
139
142
  ## Introduction
140
143
  This is the Sunholo Python project, a comprehensive toolkit for working with language models and vector stores on Google Cloud Platform. It provides a wide range of functionalities and utilities to facilitate the development and deployment of language model applications.
@@ -1,7 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- # Define your base version
4
- version = '0.86.1'
3
+ version = '0.88.0'
5
4
 
6
5
  setup(
7
6
  name='sunholo',
@@ -29,7 +28,6 @@ setup(
29
28
  install_requires=[
30
29
  # Base dependencies
31
30
  "google-auth", # to check if on gcp
32
- #"tenacity==8.3.0", #TODO: remove soon
33
31
  "ruamel.yaml",
34
32
  "langchain>=0.2.12",
35
33
  "langchain_experimental>=0.0.61",
@@ -78,6 +76,7 @@ setup(
78
76
  "psutil",
79
77
  "psycopg2-binary",
80
78
  "pypdf",
79
+ "python-hcl2",
81
80
  "python-socketio",
82
81
  "pytesseract",
83
82
  "rich",
@@ -160,6 +159,9 @@ setup(
160
159
  'xlwings',
161
160
  'requests',
162
161
  'rich'
162
+ ],
163
+ 'iac':[
164
+ 'python-hcl2'
163
165
  ]
164
166
 
165
167
  },
@@ -19,6 +19,7 @@ from . import patches
19
19
  from . import pubsub
20
20
  from . import qna
21
21
  from . import streaming
22
+ from . import terraform
22
23
  from . import tools
23
24
  from . import utils
24
25
  from . import vertex
@@ -46,6 +47,7 @@ __all__ = ['agents',
46
47
  'pubsub',
47
48
  'qna',
48
49
  'streaming',
50
+ 'terraform',
49
51
  'tools',
50
52
  'utils',
51
53
  'vertex',
@@ -53,10 +53,11 @@ if __name__ == "__main__":
53
53
  ```
54
54
 
55
55
  """
56
- def __init__(self, app, stream_interpreter, vac_interpreter):
56
+ def __init__(self, app, stream_interpreter, vac_interpreter, additional_routes=None):
57
57
  self.app = app
58
58
  self.stream_interpreter = stream_interpreter
59
59
  self.vac_interpreter = vac_interpreter
60
+ self.additional_routes = additional_routes if additional_routes is not None else []
60
61
  self.register_routes()
61
62
 
62
63
  def register_routes(self):
@@ -82,6 +83,47 @@ if __name__ == "__main__":
82
83
  # OpenAI compatible endpoint
83
84
  self.app.route('/openai/v1/chat/completions', methods=['POST'])(self.handle_openai_compatible_endpoint)
84
85
  self.app.route('/openai/v1/chat/completions/<vector_name>', methods=['POST'])(self.handle_openai_compatible_endpoint)
86
+ # Register additional routes
87
+ self.register_additional_routes()
88
+
89
+ def register_additional_routes(self):
90
+ """
91
+ Registers additional custom routes provided during initialization.
92
+
93
+ Example:
94
+ ```python
95
+ from flask import Flask, jsonify
96
+ from agents.flask import VACRoutes
97
+
98
+ app = Flask(__name__)
99
+
100
+ def stream_interpreter(question, vector_name, chat_history, **kwargs):
101
+ # Implement your streaming logic
102
+ ...
103
+
104
+ def vac_interpreter(question, vector_name, chat_history, **kwargs):
105
+ # Implement your static VAC logic
106
+ ...
107
+
108
+ def custom_handler():
109
+ return jsonify({"message": "Custom route!"})
110
+
111
+ custom_routes = [
112
+ {
113
+ "rule": "/custom",
114
+ "methods": ["GET"],
115
+ "handler": custom_handler
116
+ }
117
+ ]
118
+
119
+ vac_routes = VACRoutes(app, stream_interpreter, vac_interpreter, additional_routes=custom_routes)
120
+
121
+ if __name__ == "__main__":
122
+ app.run(debug=True)
123
+ ```
124
+ """
125
+ for route in self.additional_routes:
126
+ self.app.route(route["rule"], methods=route["methods"])(route["handler"])
85
127
 
86
128
  def home(self):
87
129
  return jsonify("OK")
@@ -121,7 +163,7 @@ if __name__ == "__main__":
121
163
  def handle_stream_vac(self, vector_name):
122
164
  observed_stream_interpreter = observe()(self.stream_interpreter)
123
165
  prep = self.prep_vac(request, vector_name)
124
- log.debug(f"Processing prep: {prep}")
166
+ log.info(f"Processing prep: {prep}")
125
167
  trace = prep["trace"]
126
168
  span = prep["span"]
127
169
  command_response = prep["command_response"]
@@ -438,8 +480,10 @@ if __name__ == "__main__":
438
480
  data["image_uri"] = image_uri
439
481
  data["mime"] = mime_type
440
482
  except Exception as e:
483
+ log.error(traceback.format_exc())
441
484
  return jsonify({'error': str(e), 'traceback': traceback.format_exc()}), 500
442
485
  else:
486
+ log.error("No file selected")
443
487
  return jsonify({"error": "No file selected"}), 400
444
488
  else:
445
489
  return jsonify({"error": "Unsupported content type"}), 400
@@ -12,6 +12,7 @@ from .swagger import setup_swagger_subparser
12
12
  from .vertex import setup_vertex_subparser
13
13
  from ..llamaindex import setup_llamaindex_subparser
14
14
  from ..excel import setup_excel_subparser
15
+ from ..terraform import setup_tfvarseditor_subparser
15
16
 
16
17
  from ..utils import ConfigManager
17
18
  from ..utils.version import sunholo_version
@@ -65,13 +66,13 @@ def main(args=None):
65
66
  parser.add_argument('--debug', action='store_true', help='Enable debug output')
66
67
  parser.add_argument('--project', default=default_project, help='GCP project to list Cloud Run services from.')
67
68
  parser.add_argument('--region', default=default_region, help='Region to list Cloud Run services from.')
68
- parser.add_argument('--version', action='store_true', help='Show the version and exit')
69
+ parser.add_argument('-v', '--version', action='store_true', help='Show the version and exit')
69
70
 
70
71
  subparsers = parser.add_subparsers(title='commands',
71
72
  description='Valid commands',
72
73
  help='Commands',
73
74
  dest='command',
74
- required=True)
75
+ required=False)
75
76
 
76
77
  # deploy command
77
78
  setup_deploy_subparser(subparsers)
@@ -95,11 +96,18 @@ def main(args=None):
95
96
  setup_llamaindex_subparser(subparsers)
96
97
  # excel
97
98
  setup_excel_subparser(subparsers)
99
+ # terraform
100
+ setup_tfvarseditor_subparser(subparsers)
98
101
 
99
102
  #TODO: add database setup commands: alloydb and supabase
100
103
 
101
104
  args = parser.parse_args(args)
102
105
 
106
+ # Handle global flags
107
+ if args.version:
108
+ console.print(sunholo_version())
109
+ return
110
+
103
111
  if args.debug:
104
112
  log.setLevel(logging.DEBUG)
105
113
  logging.getLogger().setLevel(logging.DEBUG)
@@ -107,14 +115,9 @@ def main(args=None):
107
115
  log.setLevel(logging.WARNING)
108
116
  logging.getLogger().setLevel(logging.WARNING)
109
117
 
110
- if args.version:
111
- sunholo_version()
112
- return
113
-
118
+ # Handle subcommand
114
119
  if hasattr(args, 'func'):
115
120
  args.func(args)
116
121
  else:
117
122
  parser.print_help()
118
123
 
119
- if __name__ == "__main__":
120
- main()
@@ -70,6 +70,8 @@ def handle_base64_image(base64_data: str, vector_name: str, extension: str):
70
70
 
71
71
 
72
72
  def resolve_bucket(vector_name):
73
+ bucket_name = None
74
+
73
75
  if os.getenv('EXTENSIONS_BUCKET'):
74
76
  log.warning('Resolving to EXTENSIONS_BUCKET environment variable')
75
77
  return os.getenv('EXTENSIONS_BUCKET')
@@ -144,6 +146,7 @@ def add_file_to_gcs(filename: str,
144
146
  hour_prev = (now - datetime.timedelta(hours=1)).strftime("%H")
145
147
 
146
148
  if os.getenv('EXTENSIONS_BUCKET'):
149
+ log.warning(f"setting {bucket_filepath=} to {os.path.basename(filename)} basename due to EXTENSIONS_BUCKET setting")
147
150
  bucket_filepath = os.path.basename(filename)
148
151
 
149
152
  if not vector_name:
@@ -202,6 +202,10 @@ class GenAIFunctionProcessor:
202
202
  """
203
203
  api_requests_and_responses = []
204
204
 
205
+ if not full_response:
206
+ log.info("No response was found to process")
207
+ return api_requests_and_responses
208
+
205
209
  # Loop through each part in the response to handle multiple function calls
206
210
  #TODO: async
207
211
  for part in full_response.candidates[0].content.parts:
@@ -284,7 +288,7 @@ class GenAIFunctionProcessor:
284
288
  if generation_config is None:
285
289
  generation_config = {
286
290
  "temperature": 0.1,
287
- "max_output_tokens": 4000,
291
+ "max_output_tokens": 8000,
288
292
  }
289
293
 
290
294
  # Extract the functions from the dictionary to pass into the model
@@ -0,0 +1 @@
1
+ from .tfvars_editor import setup_tfvarseditor_subparser, TerraformVarsEditor
@@ -0,0 +1,270 @@
1
+ try:
2
+ import hcl2
3
+ except ImportError:
4
+ hcl2 = None
5
+
6
+ import json
7
+ import subprocess
8
+ import os
9
+ from typing import Dict, Any
10
+ from ..custom_logging import log
11
+
12
+ try:
13
+ from ..cli.sun_rich import console
14
+ except ImportError:
15
+ console = None
16
+
17
+ class TerraformVarsEditor:
18
+ """
19
+ A class to manage and safely edit Terraform .tfvars files.
20
+
21
+ This class allows you to update specific keys in a .tfvars file with new data
22
+ and ensures that the changes only take effect if Terraform validation passes.
23
+
24
+ Attributes:
25
+ ----------
26
+ tfvars_file : str
27
+ The path to the .tfvars file to be edited.
28
+ terraform_dir : str
29
+ The directory where Terraform commands will be executed (default is current directory).
30
+ tfvars_data : dict
31
+ The content of the .tfvars file loaded into a dictionary.
32
+
33
+ Methods:
34
+ -------
35
+ _load_tfvars() -> Dict[str, Any]
36
+ Loads the .tfvars file into a dictionary.
37
+ _save_tfvars() -> None
38
+ Saves the current state of the dictionary back to the .tfvars file.
39
+ _backup_tfvars() -> str
40
+ Creates a backup of the current .tfvars file.
41
+ _restore_tfvars(backup_file: str) -> None
42
+ Restores the .tfvars file from the backup.
43
+ update_or_add_instance(main_key: str, instance_name: str, instance_data: Dict[str, Any]) -> None
44
+ Adds or updates an instance under a specified top-level key in the .tfvars file.
45
+ validate_terraform() -> bool
46
+ Runs `terraform validate` in the specified directory.
47
+ update_from_json(json_file: str, main_key: str) -> None
48
+ Updates the .tfvars file based on the content of a JSON file and validates the changes.
49
+ """
50
+
51
+ def __init__(self, tfvars_file: str, terraform_dir: str = '.') -> None:
52
+ """
53
+ Initializes the TerraformVarsEditor with the given .tfvars file and Terraform directory.
54
+
55
+ Parameters:
56
+ ----------
57
+ tfvars_file : str
58
+ The path to the .tfvars file to be edited.
59
+ terraform_dir : str
60
+ The directory where Terraform commands will be executed (default is current directory).
61
+
62
+ Example:
63
+ -------
64
+ editor = TerraformVarsEditor('example.tfvars', '/path/to/terraform/config')
65
+ """
66
+ if hcl2 is None:
67
+ raise ImportError('hcl2 is required for parsing terraform files, install via `pip install sunholo[iac]`')
68
+
69
+ self.tfvars_file = tfvars_file
70
+ self.terraform_dir = terraform_dir
71
+ self.tfvars_data = self._load_tfvars()
72
+
73
+ def _load_tfvars(self) -> Dict[str, Any]:
74
+ """
75
+ Loads the .tfvars file into a dictionary.
76
+
77
+ Returns:
78
+ -------
79
+ dict
80
+ The content of the .tfvars file.
81
+
82
+ Example:
83
+ -------
84
+ data = self._load_tfvars()
85
+ """
86
+ with open(self.tfvars_file, 'r') as file:
87
+ return hcl2.load(file)
88
+
89
+ def _save_tfvars(self) -> None:
90
+ """
91
+ Saves the current state of the dictionary back to the .tfvars file.
92
+
93
+ Example:
94
+ -------
95
+ self._save_tfvars()
96
+ """
97
+ with open(self.tfvars_file, 'w') as file:
98
+ for key, value in self.tfvars_data.items():
99
+ file.write(f'{key} = {json.dumps(value, indent=2)}\n')
100
+
101
+ def _backup_tfvars(self) -> str:
102
+ """
103
+ Creates a backup of the current .tfvars file.
104
+
105
+ Returns:
106
+ -------
107
+ str
108
+ The path to the backup file.
109
+
110
+ Example:
111
+ -------
112
+ backup_file = self._backup_tfvars()
113
+ """
114
+ backup_file = f"{self.tfvars_file}.bak"
115
+ os.rename(self.tfvars_file, backup_file)
116
+ return backup_file
117
+
118
+ def _restore_tfvars(self, backup_file: str) -> None:
119
+ """
120
+ Restores the .tfvars file from the backup.
121
+
122
+ Parameters:
123
+ ----------
124
+ backup_file : str
125
+ The path to the backup file to restore from.
126
+
127
+ Example:
128
+ -------
129
+ self._restore_tfvars('example.tfvars.bak')
130
+ """
131
+ os.rename(backup_file, self.tfvars_file)
132
+
133
+ def update_or_add_instance(self, main_key: str, instance_name: str, instance_data: Dict[str, Any]) -> None:
134
+ """
135
+ Adds or updates an instance under a specified top-level key in the .tfvars file.
136
+
137
+ Parameters:
138
+ ----------
139
+ main_key : str
140
+ The top-level key in the .tfvars file (e.g., "cloud_run").
141
+ instance_name : str
142
+ The name of the instance to add or update.
143
+ instance_data : dict
144
+ The dictionary containing the instance data.
145
+
146
+ Example:
147
+ -------
148
+ editor.update_or_add_instance('cloud_run', 'new_service', {'cpu': '1', 'memory': '2Gi'})
149
+ """
150
+ if main_key not in self.tfvars_data:
151
+ self.tfvars_data[main_key] = {}
152
+
153
+ self.tfvars_data[main_key][instance_name] = instance_data
154
+
155
+ def validate_terraform(self) -> bool:
156
+ """
157
+ Runs `terraform validate` in the specified directory.
158
+
159
+ Returns:
160
+ -------
161
+ bool
162
+ True if validation passes, False otherwise.
163
+
164
+ Example:
165
+ -------
166
+ if self.validate_terraform():
167
+ print("Validation passed.")
168
+ """
169
+ result = subprocess.run(['terraform', 'validate'], cwd=self.terraform_dir, capture_output=True, text=True)
170
+
171
+ if result.returncode == 0:
172
+ log.info("Terraform validation passed.")
173
+ return True
174
+ else:
175
+ log.error("Terraform validation failed.")
176
+ print(result.stdout)
177
+ print(result.stderr)
178
+ return False
179
+
180
+ def update_from_json(self, json_file: str, main_key: str) -> None:
181
+ """
182
+ Updates the .tfvars file based on the content of a JSON file and validates the changes.
183
+
184
+ Parameters:
185
+ ----------
186
+ json_file : str
187
+ The path to the JSON file with the new instance data.
188
+ main_key : str
189
+ The top-level key in the .tfvars file (e.g., "cloud_run").
190
+
191
+ Example:
192
+ -------
193
+ editor.update_from_json('update.json', 'cloud_run')
194
+ """
195
+ with open(json_file, 'r') as file:
196
+ data = json.load(file)
197
+
198
+ # Update the tfvars data in memory
199
+ for instance_name, instance_data in data.get(main_key, {}).items():
200
+ self.update_or_add_instance(main_key, instance_name, instance_data)
201
+
202
+ # Backup the original .tfvars file
203
+ backup_file = self._backup_tfvars()
204
+
205
+ # Temporarily save the updated data to the original file location
206
+ self._save_tfvars()
207
+
208
+ # Attempt to validate the changes with Terraform
209
+ if not self.validate_terraform():
210
+ # If validation fails, restore the original file from the backup
211
+ self._restore_tfvars(backup_file)
212
+ log.error(f"Changes aborted, original {self.tfvars_file} restored.")
213
+ else:
214
+ log.info(f"Terraform validation passed, changes saved to {self.tfvars_file}.")
215
+ os.remove(backup_file) # Remove the backup if validation passes
216
+
217
+ def tfvars_command(args):
218
+ """
219
+ Executes the tfvars command based on parsed arguments.
220
+
221
+ Args:
222
+ args: The parsed command-line arguments.
223
+ """
224
+
225
+ if console is None:
226
+ raise ImportError("Need cli tools to use `sunholo tfvars` - install via `pip install sunholo[cli]`")
227
+
228
+ # Parse the JSON string to a dictionary
229
+ try:
230
+ instance_data: Dict[str, Any] = json.loads(args.json_data)
231
+ except json.JSONDecodeError as e:
232
+ console.print(f"[bold red]Error parsing JSON data: {e}[/bold red]")
233
+ return
234
+
235
+ # Create an instance of TerraformVarsEditor
236
+ editor = TerraformVarsEditor(args.tfvars_file, args.terraform_dir)
237
+
238
+ # Add or update the instance
239
+ editor.update_or_add_instance(args.main_key, args.instance_name, instance_data)
240
+
241
+ # Validate the Terraform configuration
242
+ if editor.validate_terraform():
243
+ console.print(f"Successfully updated '{args.instance_name}' under '{args.main_key}' in '{args.tfvars_file}'.")
244
+ else:
245
+ console.print(f"[bold red]Failed to update '{args.instance_name}'. The changes have been rolled back.[/bold red]")
246
+
247
+ def setup_tfvarseditor_subparser(subparsers):
248
+ """
249
+ Sets up an argparse subparser for the 'tfvars' command.
250
+
251
+ Args:
252
+ subparsers: The subparsers object from argparse.ArgumentParser().
253
+ """
254
+ # TFVars subparser setup
255
+ tfvars_parser = subparsers.add_parser('tfvars', help='Manage Terraform .tfvars files')
256
+ tfvars_subparsers = tfvars_parser.add_subparsers(dest='action', help='TFVars subcommands')
257
+
258
+ # TFVars add command
259
+ add_parser = tfvars_subparsers.add_parser('add', help='Add or update an instance in a .tfvars file')
260
+ add_parser.add_argument('tfvars_file', help='Path to the .tfvars file')
261
+ add_parser.add_argument('main_key', help='The main key under which the instance is added (e.g., "cloud_run")')
262
+ add_parser.add_argument('instance_name', help='The name of the instance to add or update')
263
+ add_parser.add_argument('json_data', help='JSON string representing the instance data')
264
+ add_parser.add_argument('--terraform-dir', default='.', help='The directory where Terraform is initialized')
265
+
266
+ tfvars_parser.set_defaults(func=tfvars_command)
267
+
268
+ # If no subcommand is provided, print the help message
269
+ tfvars_parser.set_defaults(func=lambda args: tfvars_parser.print_help() if args.action is None else tfvars_command)
270
+
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.86.1
3
+ Version: 0.88.0
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.86.1.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.88.0.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -64,6 +64,7 @@ Requires-Dist: playwright; extra == "all"
64
64
  Requires-Dist: psutil; extra == "all"
65
65
  Requires-Dist: psycopg2-binary; extra == "all"
66
66
  Requires-Dist: pypdf; extra == "all"
67
+ Requires-Dist: python-hcl2; extra == "all"
67
68
  Requires-Dist: python-socketio; extra == "all"
68
69
  Requires-Dist: pytesseract; extra == "all"
69
70
  Requires-Dist: rich; extra == "all"
@@ -135,6 +136,8 @@ Provides-Extra: excel
135
136
  Requires-Dist: xlwings; extra == "excel"
136
137
  Requires-Dist: requests; extra == "excel"
137
138
  Requires-Dist: rich; extra == "excel"
139
+ Provides-Extra: iac
140
+ Requires-Dist: python-hcl2; extra == "iac"
138
141
 
139
142
  ## Introduction
140
143
  This is the Sunholo Python project, a comprehensive toolkit for working with language models and vector stores on Google Cloud Platform. It provides a wide range of functionalities and utilities to facilitate the development and deployment of language model applications.
@@ -130,6 +130,8 @@ sunholo/streaming/stream_lookup.py
130
130
  sunholo/streaming/streaming.py
131
131
  sunholo/summarise/__init__.py
132
132
  sunholo/summarise/summarise.py
133
+ sunholo/terraform/__init__.py
134
+ sunholo/terraform/tfvars_editor.py
133
135
  sunholo/tools/__init__.py
134
136
  sunholo/tools/web_browser.py
135
137
  sunholo/utils/__init__.py
@@ -45,6 +45,7 @@ playwright
45
45
  psutil
46
46
  psycopg2-binary
47
47
  pypdf
48
+ python-hcl2
48
49
  python-socketio
49
50
  pytesseract
50
51
  rich
@@ -110,6 +111,9 @@ langfuse
110
111
  python-socketio
111
112
  requests
112
113
 
114
+ [iac]
115
+ python-hcl2
116
+
113
117
  [openai]
114
118
  langchain-openai
115
119
  tiktoken
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