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.
- {sunholo-0.86.1 → sunholo-0.88.0}/PKG-INFO +5 -2
- {sunholo-0.86.1 → sunholo-0.88.0}/setup.py +5 -3
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/__init__.py +2 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/vac_routes.py +46 -2
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/cli.py +11 -8
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/add_file.py +3 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/process_funcs_cls.py +5 -1
- sunholo-0.88.0/sunholo/terraform/__init__.py +1 -0
- sunholo-0.88.0/sunholo/terraform/tfvars_editor.py +270 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/PKG-INFO +5 -2
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/SOURCES.txt +2 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/requires.txt +4 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/LICENSE.txt +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/MANIFEST.in +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/README.md +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/setup.cfg +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/route.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/agents/swagger.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/archive/archive.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/refresh.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/auth/run.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/auth.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/blobs.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/discord.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/azure.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/images.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/configs.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/embedder.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/swagger.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/cli/vertex.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/llm.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/retriever.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/custom_logging.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/database.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/database/uuid.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/excel/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/excel/plugin.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/init.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/genai/safety.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/qna/retry.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/tools/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/api_key.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/config.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/config_class.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/parsers.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/utils/version.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/init.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/safety.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.86.1 → sunholo-0.88.0}/tests/test_chat_history.py +0 -0
- {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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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=
|
|
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
|
-
|
|
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":
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|