sunholo 0.88.3__tar.gz → 0.89.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sunholo-0.88.3 → sunholo-0.89.1}/PKG-INFO +2 -2
- {sunholo-0.88.3 → sunholo-0.89.1}/setup.py +1 -1
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/cli_init.py +93 -8
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/genai/process_funcs_cls.py +19 -8
- sunholo-0.89.1/sunholo/langfuse/evals.py +72 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/terraform/tfvars_editor.py +19 -4
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/parsers.py +34 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo.egg-info/PKG-INFO +2 -2
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo.egg-info/SOURCES.txt +1 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/LICENSE.txt +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/MANIFEST.in +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/README.md +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/setup.cfg +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/flask/vac_routes.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/route.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/agents/swagger.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/archive/archive.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/auth/refresh.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/auth/run.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/azure/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/azure/auth.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/azure/blobs.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/bots/discord.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/azure.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/images.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/cli.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/configs.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/embedder.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/swagger.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/cli/vertex.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/components/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/components/llm.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/components/retriever.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/custom_logging.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/database.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/database/uuid.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/excel/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/excel/plugin.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/genai/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/genai/init.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/genai/safety.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/qna/retry.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/tools/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/api_key.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/config.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/config_class.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/utils/version.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/init.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/safety.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/tests/test_chat_history.py +0 -0
- {sunholo-0.88.3 → sunholo-0.89.1}/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.89.1
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.89.1.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import yaml
|
|
2
3
|
import shutil
|
|
3
4
|
from ..utils.config import get_module_filepath
|
|
5
|
+
from ..utils.parsers import sanitize_cloudrun_name
|
|
4
6
|
|
|
5
7
|
def init_project(args):
|
|
6
8
|
"""
|
|
@@ -28,7 +30,7 @@ This will create a new directory named `my_genai_project` with the template file
|
|
|
28
30
|
"""
|
|
29
31
|
from .sun_rich import console
|
|
30
32
|
|
|
31
|
-
project_name = args.project_name
|
|
33
|
+
project_name = sanitize_cloudrun_name(args.project_name)
|
|
32
34
|
current_dir = os.getcwd() # This captures the current directory where the command is run
|
|
33
35
|
project_dir = os.path.join(current_dir, project_name)
|
|
34
36
|
|
|
@@ -51,6 +53,8 @@ This will create a new directory named `my_genai_project` with the template file
|
|
|
51
53
|
shutil.copy(src_path, dest_path)
|
|
52
54
|
elif os.path.isdir(src_path):
|
|
53
55
|
shutil.copytree(src_path, dest_path)
|
|
56
|
+
|
|
57
|
+
|
|
54
58
|
|
|
55
59
|
# Determine the location of the generated.tfvars file
|
|
56
60
|
terraform_dir = args.terraform_dir or os.getenv('MULTIVAC_TERRAFORM_DIR')
|
|
@@ -62,19 +66,15 @@ This will create a new directory named `my_genai_project` with the template file
|
|
|
62
66
|
# Get the service account, either from the CLI argument or default
|
|
63
67
|
service_account = args.service_account or "sa-llmops" # Default service account
|
|
64
68
|
|
|
65
|
-
# Determine the relative path for the cloud build included directories
|
|
66
|
-
def get_relative_application_path(full_path: str, base_dir: str) -> str:
|
|
67
|
-
application_base_index = full_path.find("application/")
|
|
68
|
-
if application_base_index != -1:
|
|
69
|
-
return full_path[application_base_index:]
|
|
70
|
-
return os.path.relpath(full_path, base_dir)
|
|
71
|
-
|
|
72
69
|
# Paths to be included in the cloud build (based on the current working directory)
|
|
73
70
|
# We want paths to start from 'application/system_services/{project_name}'
|
|
74
71
|
relative_base = os.path.relpath(current_dir, os.path.join(current_dir, "..", ".."))
|
|
75
72
|
included_path = os.path.join(relative_base, project_name, "**")
|
|
76
73
|
cloud_build_path = os.path.join(relative_base, project_name, "cloudbuild.yaml")
|
|
77
74
|
|
|
75
|
+
update_cloudbuild_template(project_dir, project_name, os.path.join(relative_base, project_name))
|
|
76
|
+
write_vac_config(project_dir, project_name)
|
|
77
|
+
|
|
78
78
|
# Define the cloud_run configuration for 'discord-server' with the correct project_dir path
|
|
79
79
|
cloud_run_config = {
|
|
80
80
|
project_name: {
|
|
@@ -118,6 +118,91 @@ This will create a new directory named `my_genai_project` with the template file
|
|
|
118
118
|
)
|
|
119
119
|
console.rule()
|
|
120
120
|
|
|
121
|
+
def update_cloudbuild_template(project_dir: str, service_name: str, build_folder: str):
|
|
122
|
+
"""
|
|
123
|
+
Updates the cloudbuild.yaml template file by replacing the `CHANGE_ME` placeholders with actual values.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
-----
|
|
127
|
+
project_dir : str
|
|
128
|
+
The directory where the project and cloudbuild.yaml are located.
|
|
129
|
+
service_name : str
|
|
130
|
+
The name of the service to be used in Cloud Run.
|
|
131
|
+
build_folder : str
|
|
132
|
+
The build folder where the Docker build will take place.
|
|
133
|
+
|
|
134
|
+
Example:
|
|
135
|
+
-------
|
|
136
|
+
update_cloudbuild_template('/path/to/project', 'my_service', 'src')
|
|
137
|
+
"""
|
|
138
|
+
cloudbuild_path = os.path.join(project_dir, "cloudbuild.yaml")
|
|
139
|
+
|
|
140
|
+
# Define the substitutions to replace CHANGE_ME
|
|
141
|
+
substitutions = {
|
|
142
|
+
"_SERVICE_NAME": service_name,
|
|
143
|
+
"_BUILD_FOLDER": build_folder,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Read the cloudbuild.yaml template
|
|
147
|
+
with open(cloudbuild_path, 'r') as file:
|
|
148
|
+
content = file.read()
|
|
149
|
+
|
|
150
|
+
# Replace each placeholder with its corresponding value
|
|
151
|
+
for placeholder, value in substitutions.items():
|
|
152
|
+
content = content.replace(f"{placeholder}: CHANGE_ME", f"{placeholder}: {value}")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# Write the updated content back to cloudbuild.yaml
|
|
156
|
+
with open(cloudbuild_path, 'w') as file:
|
|
157
|
+
file.write(content)
|
|
158
|
+
|
|
159
|
+
print(f"cloudbuild.yaml updated successfully with service name '{service_name}' and build folder '{build_folder}'.")
|
|
160
|
+
|
|
161
|
+
def write_vac_config(project_dir: str, service_name: str):
|
|
162
|
+
"""
|
|
163
|
+
Writes the vac_config.yaml file with the provided service name as the key.
|
|
164
|
+
"""
|
|
165
|
+
vac_config_content = {
|
|
166
|
+
'kind': 'vacConfig',
|
|
167
|
+
'apiVersion': 'v1',
|
|
168
|
+
'vac': {
|
|
169
|
+
service_name: { # Use the service name here
|
|
170
|
+
'llm': 'vertex',
|
|
171
|
+
'model': 'gemini-1.5-pro-preview-0514',
|
|
172
|
+
'agent': 'vertex-genai',
|
|
173
|
+
'display_name': 'Template VAC',
|
|
174
|
+
'memory': [
|
|
175
|
+
{
|
|
176
|
+
'llamaindex-native': {
|
|
177
|
+
'vectorstore': 'llamaindex'
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
'gcp_config': {
|
|
182
|
+
'project_id': 'llamaindex_project',
|
|
183
|
+
'location': 'europe-west1',
|
|
184
|
+
'rag_id': '1234544343434' # Replace with actual RAG ID
|
|
185
|
+
},
|
|
186
|
+
'chunker': {
|
|
187
|
+
'chunk_size': 1000,
|
|
188
|
+
'overlap': 200
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
config_dir = os.path.join(project_dir, 'config')
|
|
195
|
+
if not os.path.exists(config_dir):
|
|
196
|
+
os.makedirs(config_dir)
|
|
197
|
+
|
|
198
|
+
vac_config_path = os.path.join(config_dir, 'vac_config.yaml')
|
|
199
|
+
|
|
200
|
+
# Write the YAML configuration to the file
|
|
201
|
+
with open(vac_config_path, 'w') as file:
|
|
202
|
+
yaml.dump(vac_config_content, file, default_flow_style=False)
|
|
203
|
+
|
|
204
|
+
print(f"{vac_config_path} written successfully with service name '{service_name}'.")
|
|
205
|
+
|
|
121
206
|
|
|
122
207
|
def setup_init_subparser(subparsers):
|
|
123
208
|
"""
|
|
@@ -109,14 +109,24 @@ class GenAIFunctionProcessor:
|
|
|
109
109
|
work_on = api_requests_and_responses or self.last_api_requests_and_responses
|
|
110
110
|
parts = []
|
|
111
111
|
for part in work_on:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
try:
|
|
113
|
+
parts.append(
|
|
114
|
+
Part(
|
|
115
|
+
function_response=genai.protos.FunctionResponse(
|
|
116
|
+
name=part[0],
|
|
117
|
+
response={"result": part[2], "args": json.dumps(part[1])}
|
|
118
|
+
)
|
|
117
119
|
)
|
|
118
120
|
)
|
|
119
|
-
|
|
121
|
+
except Exception as err:
|
|
122
|
+
parts.append(
|
|
123
|
+
Part(
|
|
124
|
+
function_response=genai.protos.FunctionResponse(
|
|
125
|
+
name=part[0],
|
|
126
|
+
response={"result": f"ERROR: {str(err)}"}
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
)
|
|
120
130
|
|
|
121
131
|
return parts
|
|
122
132
|
|
|
@@ -212,14 +222,15 @@ class GenAIFunctionProcessor:
|
|
|
212
222
|
if fn := part.function_call:
|
|
213
223
|
# Extract parameters for the function call
|
|
214
224
|
function_name = fn.name
|
|
215
|
-
|
|
225
|
+
params_obj = {key: val for key, val in fn.args.items()}
|
|
226
|
+
params = ', '.join(f'{key}={val}' for key, val in params_obj.items())
|
|
216
227
|
log.info(f"Executing {function_name} with params {params}")
|
|
217
228
|
|
|
218
229
|
# Check if the function is in our dictionary of available functions
|
|
219
230
|
if function_name in self.funcs:
|
|
220
231
|
try:
|
|
221
232
|
# Execute the function with the provided parameters
|
|
222
|
-
result = self.funcs[function_name](**
|
|
233
|
+
result = self.funcs[function_name](**params_obj)
|
|
223
234
|
log.info(f"Got result from {function_name}: {result}")
|
|
224
235
|
except Exception as err:
|
|
225
236
|
error_message = f"Error in {function_name}: {str(err)}"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from ..pubsub import decode_pubsub_message
|
|
3
|
+
from langfuse import Langfuse
|
|
4
|
+
from ..custom_logging import log
|
|
5
|
+
|
|
6
|
+
# Example of how eval_funcs might be structured
|
|
7
|
+
def eval_length(trace):
|
|
8
|
+
"""
|
|
9
|
+
An example of how eval_funcs might be structured.
|
|
10
|
+
Must output a dictionary with 'score' and 'reason' keys.
|
|
11
|
+
"""
|
|
12
|
+
# Example evaluation logic
|
|
13
|
+
return {
|
|
14
|
+
"score": len(trace.output), # Example: length of the output text
|
|
15
|
+
"reason": "Length of the output text"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
def pubsub_to_evals(data: dict, eval_funcs: list=[eval_length]) -> dict:
|
|
19
|
+
"""
|
|
20
|
+
Process a Pub/Sub message and run evaluations using the provided evaluation functions.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
data (dict): The Pub/Sub message data.
|
|
24
|
+
eval_funcs (list): A list of evaluation functions to run. Each function should return a dict with 'score' and 'reason'.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# Decode the message
|
|
28
|
+
message_data, metadata, vector_name = decode_pubsub_message(data)
|
|
29
|
+
|
|
30
|
+
if 'trace_id' not in message_data:
|
|
31
|
+
raise ValueError('No trace_id found in message data')
|
|
32
|
+
|
|
33
|
+
# Initialize Langfuse with environment variables
|
|
34
|
+
langfuse = Langfuse(
|
|
35
|
+
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
|
|
36
|
+
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
|
|
37
|
+
host=os.environ["LANGFUSE_HOST"]
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
trace_id = message_data.pop('trace_id', None)
|
|
41
|
+
|
|
42
|
+
# Fetch the latest trace (or modify as needed to fetch a specific trace)
|
|
43
|
+
trace = langfuse.fetch_trace(id=trace_id)
|
|
44
|
+
|
|
45
|
+
if trace.output is None:
|
|
46
|
+
raise ValueError("Trace {trace.name} had no generated output, it was skipped")
|
|
47
|
+
|
|
48
|
+
# Run the evaluation functions
|
|
49
|
+
eval_results = []
|
|
50
|
+
for eval_func in eval_funcs:
|
|
51
|
+
eval_result = eval_func(trace) # Assuming eval_func returns a dict with 'score' and 'reason'
|
|
52
|
+
eval_results.append(eval_result)
|
|
53
|
+
|
|
54
|
+
eval_name = eval_func.__name__
|
|
55
|
+
|
|
56
|
+
if 'score' or 'reason' not in eval_result:
|
|
57
|
+
raise ValueError(f"Trace {trace.name} using {eval_name=} did not return a dict with 'score' and 'reason': {eval_result=}")
|
|
58
|
+
|
|
59
|
+
log.info(f"TraceId {trace.id} with name {trace.name} had {eval_name=} with score {eval_result=}")
|
|
60
|
+
|
|
61
|
+
# Submit the evaluation to Langfuse
|
|
62
|
+
langfuse.score(
|
|
63
|
+
trace_id=trace.id,
|
|
64
|
+
name=eval_name, # Use the function name as the evaluation name
|
|
65
|
+
value=eval_result["score"],
|
|
66
|
+
comment=eval_result["reason"],
|
|
67
|
+
**message_data
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
return {"trace_id": trace.id, "eval_results": eval_results}
|
|
71
|
+
|
|
72
|
+
|
|
@@ -5,6 +5,8 @@ except ImportError:
|
|
|
5
5
|
|
|
6
6
|
import json
|
|
7
7
|
import subprocess
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
import shutil
|
|
8
10
|
import os
|
|
9
11
|
import io
|
|
10
12
|
from typing import Dict, Any
|
|
@@ -75,6 +77,13 @@ class TerraformVarsEditor:
|
|
|
75
77
|
|
|
76
78
|
self.tfvars_file = tfvars_file
|
|
77
79
|
self.terraform_dir = terraform_dir
|
|
80
|
+
|
|
81
|
+
# Ensure the tfvars file exists, if not, create it
|
|
82
|
+
if not os.path.exists(self.tfvars_file):
|
|
83
|
+
log.info(f"{self.tfvars_file} does not exist. Creating a new file.")
|
|
84
|
+
with open(self.tfvars_file, 'w') as file:
|
|
85
|
+
file.write("") # Create an empty tfvars file
|
|
86
|
+
|
|
78
87
|
self.tfvars_data = self._load_tfvars()
|
|
79
88
|
|
|
80
89
|
def _load_tfvars(self) -> Dict[str, Any]:
|
|
@@ -118,8 +127,9 @@ class TerraformVarsEditor:
|
|
|
118
127
|
-------
|
|
119
128
|
backup_file = self._backup_tfvars()
|
|
120
129
|
"""
|
|
121
|
-
|
|
122
|
-
|
|
130
|
+
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
|
|
131
|
+
backup_file = f"{self.tfvars_file}.{timestamp}.bak"
|
|
132
|
+
shutil.copy2(self.tfvars_file, backup_file)
|
|
123
133
|
return backup_file
|
|
124
134
|
|
|
125
135
|
def _restore_tfvars(self, backup_file: str) -> None:
|
|
@@ -231,8 +241,10 @@ class TerraformVarsEditor:
|
|
|
231
241
|
# Attempt to validate the changes with Terraform
|
|
232
242
|
if not self.validate_terraform():
|
|
233
243
|
# If validation fails, restore the original file from the backup
|
|
244
|
+
failed_file = f"{self.tfvars_file}.failed"
|
|
245
|
+
shutil.copy2(self.tfvars_file, failed_file)
|
|
234
246
|
self._restore_tfvars(backup_file)
|
|
235
|
-
|
|
247
|
+
print(f"Changes aborted, original {self.tfvars_file} restored. Failed file: {failed_file}")
|
|
236
248
|
else:
|
|
237
249
|
log.info(f"Terraform validation passed, changes saved to {self.tfvars_file}.")
|
|
238
250
|
os.remove(backup_file) # Remove the backup if validation passes
|
|
@@ -273,8 +285,11 @@ class TerraformVarsEditor:
|
|
|
273
285
|
# Attempt to validate the changes with Terraform
|
|
274
286
|
if not self.validate_terraform():
|
|
275
287
|
# If validation fails, restore the original file from the backup
|
|
288
|
+
failed_file = f"{self.tfvars_file}.failed"
|
|
289
|
+
shutil.copy2(self.tfvars_file, failed_file)
|
|
276
290
|
self._restore_tfvars(backup_file)
|
|
277
|
-
|
|
291
|
+
|
|
292
|
+
print(f"Changes aborted, original {self.tfvars_file} restored. Failed file: {failed_file}")
|
|
278
293
|
else:
|
|
279
294
|
console.print(f"Terraform validation passed, changes saved to {self.tfvars_file}.")
|
|
280
295
|
os.remove(backup_file) # Remove the backup if validation passes
|
|
@@ -15,6 +15,40 @@ import re
|
|
|
15
15
|
import hashlib
|
|
16
16
|
import urllib.parse
|
|
17
17
|
|
|
18
|
+
def sanitize_cloudrun_name(name: str) -> str:
|
|
19
|
+
"""
|
|
20
|
+
Sanitizes the project name to be a valid Cloud Run service name.
|
|
21
|
+
|
|
22
|
+
- Converts to lowercase.
|
|
23
|
+
- Replaces invalid characters with hyphens.
|
|
24
|
+
- Ensures the name starts with a letter.
|
|
25
|
+
- Trims the name to be less than 64 characters.
|
|
26
|
+
- Removes trailing hyphens.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
name (str): The original project name.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
str: The sanitized project name.
|
|
33
|
+
"""
|
|
34
|
+
# Convert to lowercase
|
|
35
|
+
name = name.lower()
|
|
36
|
+
|
|
37
|
+
# Replace invalid characters with hyphens
|
|
38
|
+
name = re.sub(r'[^a-z0-9-]', '-', name)
|
|
39
|
+
|
|
40
|
+
# Ensure the name starts with a letter
|
|
41
|
+
if not name[0].isalpha():
|
|
42
|
+
name = 'a' + name
|
|
43
|
+
|
|
44
|
+
# Trim to 63 characters to leave room for suffixes if needed
|
|
45
|
+
name = name[:63]
|
|
46
|
+
|
|
47
|
+
# Remove trailing hyphens
|
|
48
|
+
name = name.rstrip('-')
|
|
49
|
+
|
|
50
|
+
return name
|
|
51
|
+
|
|
18
52
|
def validate_extension_id(ext_id):
|
|
19
53
|
"""
|
|
20
54
|
Ensures the passed string fits the criteria for an extension ID.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.89.1
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.89.1.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -105,6 +105,7 @@ sunholo/invoke/direct_vac_func.py
|
|
|
105
105
|
sunholo/invoke/invoke_vac_utils.py
|
|
106
106
|
sunholo/langfuse/__init__.py
|
|
107
107
|
sunholo/langfuse/callback.py
|
|
108
|
+
sunholo/langfuse/evals.py
|
|
108
109
|
sunholo/langfuse/prompts.py
|
|
109
110
|
sunholo/llamaindex/__init__.py
|
|
110
111
|
sunholo/llamaindex/get_files.py
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|