sunholo 0.88.2__tar.gz → 0.88.4__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.2 → sunholo-0.88.4}/PKG-INFO +2 -2
- {sunholo-0.88.2 → sunholo-0.88.4}/setup.py +1 -1
- sunholo-0.88.4/sunholo/cli/cli_init.py +215 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/parsers.py +34 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo.egg-info/PKG-INFO +2 -2
- sunholo-0.88.2/sunholo/cli/cli_init.py +0 -116
- {sunholo-0.88.2 → sunholo-0.88.4}/LICENSE.txt +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/MANIFEST.in +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/README.md +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/setup.cfg +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/flask/vac_routes.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/route.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/agents/swagger.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/archive/archive.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/auth/refresh.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/auth/run.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/azure/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/azure/auth.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/azure/blobs.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/bots/discord.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/azure.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/images.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/cli.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/configs.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/embedder.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/swagger.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/cli/vertex.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/components/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/components/llm.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/components/retriever.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/custom_logging.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/database.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/database/uuid.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/excel/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/excel/plugin.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/genai/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/genai/init.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/genai/safety.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/qna/retry.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/tools/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/api_key.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/config.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/config_class.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/utils/version.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/init.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/safety.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo.egg-info/SOURCES.txt +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/tests/test_chat_history.py +0 -0
- {sunholo-0.88.2 → sunholo-0.88.4}/tests/test_config.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.88.
|
|
3
|
+
Version: 0.88.4
|
|
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.88.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.88.4.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import yaml
|
|
3
|
+
import shutil
|
|
4
|
+
from ..utils.config import get_module_filepath
|
|
5
|
+
from ..utils.parsers import sanitize_cloudrun_name
|
|
6
|
+
|
|
7
|
+
def init_project(args):
|
|
8
|
+
"""
|
|
9
|
+
Initializes a new sunholo project with a basic configuration file and directory structure.
|
|
10
|
+
|
|
11
|
+
**Template Files (`templates/project`):**
|
|
12
|
+
|
|
13
|
+
A `templates/project` directory is within the `sunholo` package with the following template files in it:
|
|
14
|
+
|
|
15
|
+
* **`config/llm_config.yaml`:** A basic configuration file with placeholders for LLM settings, vector stores, etc.
|
|
16
|
+
* **`config/cloud_run_urls.json`:** A template for Cloud Run URLs.
|
|
17
|
+
* **`app.py`:** A basic Flask app that can be customized for the project.
|
|
18
|
+
* **`.gitignore`:** A gitignore file to exclude unnecessary files from version control.
|
|
19
|
+
* **`README.md`:** A README file with instructions for setting up and running the project.
|
|
20
|
+
|
|
21
|
+
**Usage:**
|
|
22
|
+
|
|
23
|
+
Users can initialize a new project using the following command:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
sunholo init my_genai_project
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This will create a new directory named `my_genai_project` with the template files, allowing users to start building their GenAI application.
|
|
30
|
+
"""
|
|
31
|
+
from .sun_rich import console
|
|
32
|
+
|
|
33
|
+
project_name = sanitize_cloudrun_name(args.project_name)
|
|
34
|
+
current_dir = os.getcwd() # This captures the current directory where the command is run
|
|
35
|
+
project_dir = os.path.join(current_dir, project_name)
|
|
36
|
+
|
|
37
|
+
console.rule(project_name)
|
|
38
|
+
console.print(f"Initializing in directory: {project_dir}")
|
|
39
|
+
|
|
40
|
+
# Create project directory
|
|
41
|
+
if os.path.exists(project_dir):
|
|
42
|
+
console.print(f"[bold red]ERROR: Directory {project_dir} already exists. Please choose a different project name.[/bold red]")
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
os.makedirs(project_dir)
|
|
46
|
+
|
|
47
|
+
# Copy template files
|
|
48
|
+
template_dir = get_module_filepath("templates/project")
|
|
49
|
+
for filename in os.listdir(template_dir):
|
|
50
|
+
src_path = os.path.join(template_dir, filename)
|
|
51
|
+
dest_path = os.path.join(project_dir, filename)
|
|
52
|
+
if os.path.isfile(src_path):
|
|
53
|
+
shutil.copy(src_path, dest_path)
|
|
54
|
+
elif os.path.isdir(src_path):
|
|
55
|
+
shutil.copytree(src_path, dest_path)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Determine the location of the generated.tfvars file
|
|
60
|
+
terraform_dir = args.terraform_dir or os.getenv('MULTIVAC_TERRAFORM_DIR')
|
|
61
|
+
if terraform_dir is None:
|
|
62
|
+
raise ValueError("Must specify a terraform_dir or use the MULTIVAC_TERRAFORM_DIR environment variable")
|
|
63
|
+
|
|
64
|
+
tfvars_file = os.path.join(terraform_dir, 'generated.tfvars')
|
|
65
|
+
|
|
66
|
+
# Get the service account, either from the CLI argument or default
|
|
67
|
+
service_account = args.service_account or "sa-llmops" # Default service account
|
|
68
|
+
|
|
69
|
+
# Paths to be included in the cloud build (based on the current working directory)
|
|
70
|
+
# We want paths to start from 'application/system_services/{project_name}'
|
|
71
|
+
relative_base = os.path.relpath(current_dir, os.path.join(current_dir, "..", ".."))
|
|
72
|
+
included_path = os.path.join(relative_base, project_name, "**")
|
|
73
|
+
cloud_build_path = os.path.join(relative_base, project_name, "cloudbuild.yaml")
|
|
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
|
+
# Define the cloud_run configuration for 'discord-server' with the correct project_dir path
|
|
79
|
+
cloud_run_config = {
|
|
80
|
+
project_name: {
|
|
81
|
+
"cpu": "1",
|
|
82
|
+
"memory": "2Gi",
|
|
83
|
+
"max_instance_count": 3,
|
|
84
|
+
"timeout_seconds": 1500,
|
|
85
|
+
"port": 8080,
|
|
86
|
+
"service_account": service_account,
|
|
87
|
+
"invokers": ["allUsers"],
|
|
88
|
+
"cloud_build": {
|
|
89
|
+
"included": [included_path],
|
|
90
|
+
"path": cloud_build_path,
|
|
91
|
+
"substitutions": {},
|
|
92
|
+
"repo_name": "",
|
|
93
|
+
"repo_owner": ""
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Initialize the TerraformVarsEditor and update the .tfvars file
|
|
100
|
+
try:
|
|
101
|
+
from ..terraform import TerraformVarsEditor
|
|
102
|
+
editor = TerraformVarsEditor(tfvars_file, terraform_dir)
|
|
103
|
+
editor.update_from_dict(cloud_run_config, 'cloud_run_autogenerated')
|
|
104
|
+
except ImportError as e:
|
|
105
|
+
console.print(f"Error initializing TerraformVarsEditor: {e}")
|
|
106
|
+
|
|
107
|
+
from rich.panel import Panel
|
|
108
|
+
|
|
109
|
+
console.print(
|
|
110
|
+
Panel((
|
|
111
|
+
"Next steps: \n"
|
|
112
|
+
f" - Navigate to [orange]{project_dir}/config[/orange] and customize VAC configuration files.\n"
|
|
113
|
+
f" - Add your own GenAI app logic to [orange]{project_dir}/vac_service.py[/orange]\n"
|
|
114
|
+
f" - Check terraform [orange]{terraform_dir}/generated.tfvars[/orange] for Multivac deployment"
|
|
115
|
+
),
|
|
116
|
+
title=f"Project [bold orange]{project_name}[/bold orange] initialized successfully.",
|
|
117
|
+
subtitle=project_dir),
|
|
118
|
+
)
|
|
119
|
+
console.rule()
|
|
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.yaml written successfully with service name '{service_name}'.")
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def setup_init_subparser(subparsers):
|
|
208
|
+
"""
|
|
209
|
+
Sets up an argparse subparser for the 'init' command.
|
|
210
|
+
"""
|
|
211
|
+
init_parser = subparsers.add_parser('init', help='Initializes a new Multivac project.')
|
|
212
|
+
init_parser.add_argument('project_name', help='The name of the new project.')
|
|
213
|
+
init_parser.add_argument('--terraform-dir', help='The directory where Terraform files will be generated.')
|
|
214
|
+
init_parser.add_argument('--service-account', help='The service account to use for Cloud Run. Defaults to "sa-llmops"')
|
|
215
|
+
init_parser.set_defaults(func=init_project)
|
|
@@ -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.88.
|
|
3
|
+
Version: 0.88.4
|
|
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.88.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.88.4.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import shutil
|
|
3
|
-
from ..utils.config import get_module_filepath
|
|
4
|
-
|
|
5
|
-
def init_project(args):
|
|
6
|
-
"""
|
|
7
|
-
Initializes a new sunholo project with a basic configuration file and directory structure.
|
|
8
|
-
|
|
9
|
-
**Template Files (`templates/project`):**
|
|
10
|
-
|
|
11
|
-
A `templates/project` directory is within the `sunholo` package with the following template files in it:
|
|
12
|
-
|
|
13
|
-
* **`config/llm_config.yaml`:** A basic configuration file with placeholders for LLM settings, vector stores, etc.
|
|
14
|
-
* **`config/cloud_run_urls.json`:** A template for Cloud Run URLs.
|
|
15
|
-
* **`app.py`:** A basic Flask app that can be customized for the project.
|
|
16
|
-
* **`.gitignore`:** A gitignore file to exclude unnecessary files from version control.
|
|
17
|
-
* **`README.md`:** A README file with instructions for setting up and running the project.
|
|
18
|
-
|
|
19
|
-
**Usage:**
|
|
20
|
-
|
|
21
|
-
Users can initialize a new project using the following command:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
sunholo init my_genai_project
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
This will create a new directory named `my_genai_project` with the template files, allowing users to start building their GenAI application.
|
|
28
|
-
"""
|
|
29
|
-
project_name = args.project_name
|
|
30
|
-
current_dir = os.getcwd() # This captures the current directory where the command is run
|
|
31
|
-
project_dir = os.path.join(current_dir, project_name)
|
|
32
|
-
|
|
33
|
-
print(f"Initializing project: {project_name} in directory: {project_dir}")
|
|
34
|
-
|
|
35
|
-
# Create project directory
|
|
36
|
-
if os.path.exists(project_dir):
|
|
37
|
-
print(f"Directory {project_dir} already exists. Please choose a different project name.")
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
os.makedirs(project_dir)
|
|
41
|
-
|
|
42
|
-
# Copy template files
|
|
43
|
-
template_dir = get_module_filepath("templates/project")
|
|
44
|
-
for filename in os.listdir(template_dir):
|
|
45
|
-
src_path = os.path.join(template_dir, filename)
|
|
46
|
-
dest_path = os.path.join(project_dir, filename)
|
|
47
|
-
if os.path.isfile(src_path):
|
|
48
|
-
shutil.copy(src_path, dest_path)
|
|
49
|
-
elif os.path.isdir(src_path):
|
|
50
|
-
shutil.copytree(src_path, dest_path)
|
|
51
|
-
|
|
52
|
-
# Determine the location of the generated.tfvars file
|
|
53
|
-
terraform_dir = args.terraform_dir or os.getenv('MULTIVAC_TERRAFORM_DIR')
|
|
54
|
-
if terraform_dir is None:
|
|
55
|
-
raise ValueError("Must specify a terraform_dir or use the MULTIVAC_TERRAFORM_DIR environment variable")
|
|
56
|
-
|
|
57
|
-
tfvars_file = os.path.join(terraform_dir, 'generated.tfvars')
|
|
58
|
-
|
|
59
|
-
# Get the service account, either from the CLI argument or default
|
|
60
|
-
service_account = args.service_account or "sa-llmops" # Default service account
|
|
61
|
-
|
|
62
|
-
# Determine the relative path for the cloud build included directories
|
|
63
|
-
def get_relative_application_path(full_path: str, base_dir: str) -> str:
|
|
64
|
-
application_base_index = full_path.find("application/")
|
|
65
|
-
if application_base_index != -1:
|
|
66
|
-
return full_path[application_base_index:]
|
|
67
|
-
return os.path.relpath(full_path, base_dir)
|
|
68
|
-
|
|
69
|
-
# Paths to be included in the cloud build (based on the current working directory)
|
|
70
|
-
# We want paths to start from 'application/system_services/{project_name}'
|
|
71
|
-
relative_base = os.path.relpath(current_dir, os.path.join(current_dir, "..", ".."))
|
|
72
|
-
included_path = os.path.join(relative_base, project_name, "**")
|
|
73
|
-
cloud_build_path = os.path.join(relative_base, project_name, "cloudbuild.yaml")
|
|
74
|
-
|
|
75
|
-
# Define the cloud_run configuration for 'discord-server' with the correct project_dir path
|
|
76
|
-
cloud_run_config = {
|
|
77
|
-
project_name: {
|
|
78
|
-
"cpu": "1",
|
|
79
|
-
"memory": "2Gi",
|
|
80
|
-
"max_instance_count": 3,
|
|
81
|
-
"timeout_seconds": 1500,
|
|
82
|
-
"port": 8080,
|
|
83
|
-
"service_account": service_account,
|
|
84
|
-
"invokers": ["allUsers"],
|
|
85
|
-
"cloud_build": {
|
|
86
|
-
"included": [included_path],
|
|
87
|
-
"path": cloud_build_path,
|
|
88
|
-
"substitutions": {},
|
|
89
|
-
"repo_name": "",
|
|
90
|
-
"repo_owner": ""
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
# Initialize the TerraformVarsEditor and update the .tfvars file
|
|
97
|
-
try:
|
|
98
|
-
from ..terraform import TerraformVarsEditor
|
|
99
|
-
editor = TerraformVarsEditor(tfvars_file, terraform_dir)
|
|
100
|
-
editor.update_from_dict(cloud_run_config, 'cloud_run')
|
|
101
|
-
print(f"{tfvars_file} file initialized and updated successfully.")
|
|
102
|
-
except ImportError as e:
|
|
103
|
-
print(f"Error initializing TerraformVarsEditor: {e}")
|
|
104
|
-
|
|
105
|
-
print(f"Project {project_name} initialized successfully.")
|
|
106
|
-
print(f"Navigate to {project_dir} and customize the configuration files in the 'config' directory.")
|
|
107
|
-
|
|
108
|
-
def setup_init_subparser(subparsers):
|
|
109
|
-
"""
|
|
110
|
-
Sets up an argparse subparser for the 'init' command.
|
|
111
|
-
"""
|
|
112
|
-
init_parser = subparsers.add_parser('init', help='Initializes a new Multivac project.')
|
|
113
|
-
init_parser.add_argument('project_name', help='The name of the new project.')
|
|
114
|
-
init_parser.add_argument('--terraform-dir', help='The directory where Terraform files will be generated.')
|
|
115
|
-
init_parser.add_argument('--service-account', help='The service account to use for Cloud Run. Defaults to "sa-llmops"')
|
|
116
|
-
init_parser.set_defaults(func=init_project)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|