sunholo 0.119.18__tar.gz → 0.120.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.119.18/src/sunholo.egg-info → sunholo-0.120.0}/PKG-INFO +5 -3
- {sunholo-0.119.18 → sunholo-0.120.0}/pyproject.toml +5 -3
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/auth/refresh.py +3 -2
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/file_handling.py +92 -60
- {sunholo-0.119.18 → sunholo-0.120.0/src/sunholo.egg-info}/PKG-INFO +5 -3
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo.egg-info/requires.txt +4 -2
- {sunholo-0.119.18 → sunholo-0.120.0}/LICENSE.txt +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/MANIFEST.in +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/README.md +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/setup.cfg +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/flask/vac_routes.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/langserve.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/route.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/agents/swagger.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/archive/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/archive/archive.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/auth/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/auth/run.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/azure/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/azure/auth.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/azure/blobs.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/bots/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/bots/discord.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/bots/webapp.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/azure.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/images.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/publish.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/cli.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/configs.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/deploy.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/embedder.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/swagger.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/cli/vertex.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/components/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/components/llm.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/components/retriever.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/custom_logging.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/alloydb.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/database.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/lancedb.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/database/uuid.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/cli.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/embedder/embed_metadata.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/excel/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/excel/plugin.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/gcs/extract_and_sign.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/genaiv2.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/images.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/init.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/genai/safety.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/langchain_types.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/langfuse/evals.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/mcp/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/mcp/cli.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/qna/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/qna/parsers.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/qna/retry.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/senses/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/senses/stream_voice.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/agent_service.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/app.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/my_log.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/tools/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/agent/vac_service.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/project/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/project/app.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/project/my_log.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/project/vac_service.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/system_services/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/system_services/app.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/templates/system_services/my_log.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/tools/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/api_key.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/big_context.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/config.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/config_class.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/gcp.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/mime.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/parsers.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/utils/version.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/init.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/safety.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo.egg-info/SOURCES.txt +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/tests/test_async.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/tests/test_async_genai2.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/tests/test_chat_history.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/tests/test_config.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/tests/test_genai2.py +0 -0
- {sunholo-0.119.18 → sunholo-0.120.0}/tests/test_unstructured.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: sunholo
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.120.0
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
5
5
|
Author-email: Holosun ApS <multivac@sunholo.com>
|
6
6
|
License: Apache License, Version 2.0
|
@@ -28,6 +28,7 @@ Provides-Extra: test
|
|
28
28
|
Requires-Dist: pytest; extra == "test"
|
29
29
|
Requires-Dist: pytest-cov; extra == "test"
|
30
30
|
Provides-Extra: all
|
31
|
+
Requires-Dist: aiofiles; extra == "all"
|
31
32
|
Requires-Dist: aiohttp; extra == "all"
|
32
33
|
Requires-Dist: anthropic[vertex]; extra == "all"
|
33
34
|
Requires-Dist: asyncpg; extra == "all"
|
@@ -50,7 +51,7 @@ Requires-Dist: google-cloud-pubsub; extra == "all"
|
|
50
51
|
Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "all"
|
51
52
|
Requires-Dist: google-cloud-texttospeech; extra == "all"
|
52
53
|
Requires-Dist: google-generativeai>=0.7.1; extra == "all"
|
53
|
-
Requires-Dist: google-genai; extra == "all"
|
54
|
+
Requires-Dist: google-genai>=0.2.2; extra == "all"
|
54
55
|
Requires-Dist: gunicorn; extra == "all"
|
55
56
|
Requires-Dist: httpcore; extra == "all"
|
56
57
|
Requires-Dist: httpx; extra == "all"
|
@@ -122,6 +123,7 @@ Requires-Dist: pytesseract; extra == "pipeline"
|
|
122
123
|
Requires-Dist: tabulate; extra == "pipeline"
|
123
124
|
Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
|
124
125
|
Provides-Extra: gcp
|
126
|
+
Requires-Dist: aiofiles; extra == "gcp"
|
125
127
|
Requires-Dist: anthropic[vertex]; extra == "gcp"
|
126
128
|
Requires-Dist: google-api-python-client; extra == "gcp"
|
127
129
|
Requires-Dist: google-auth-httplib2; extra == "gcp"
|
@@ -136,7 +138,7 @@ Requires-Dist: google-cloud-logging; extra == "gcp"
|
|
136
138
|
Requires-Dist: google-cloud-pubsub; extra == "gcp"
|
137
139
|
Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "gcp"
|
138
140
|
Requires-Dist: google-cloud-texttospeech; extra == "gcp"
|
139
|
-
Requires-Dist: google-genai; extra == "gcp"
|
141
|
+
Requires-Dist: google-genai>=0.2.2; extra == "gcp"
|
140
142
|
Requires-Dist: google-generativeai>=0.8.3; extra == "gcp"
|
141
143
|
Requires-Dist: langchain-google-genai>=2.0.0; extra == "gcp"
|
142
144
|
Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "sunholo"
|
7
|
-
version = "0.
|
7
|
+
version = "0.120.0"
|
8
8
|
description = "Large Language Model DevOps - a package to help deploy LLMs to the Cloud."
|
9
9
|
readme = "README.md"
|
10
10
|
requires-python = ">=3.10"
|
@@ -59,6 +59,7 @@ test = [
|
|
59
59
|
# any other test dependencies
|
60
60
|
]
|
61
61
|
all = [
|
62
|
+
"aiofiles",
|
62
63
|
"aiohttp",
|
63
64
|
"anthropic[vertex]",
|
64
65
|
"asyncpg",
|
@@ -81,7 +82,7 @@ all = [
|
|
81
82
|
"google-cloud-discoveryengine>=0.13.4",
|
82
83
|
"google-cloud-texttospeech",
|
83
84
|
"google-generativeai>=0.7.1",
|
84
|
-
"google-genai",
|
85
|
+
"google-genai>=0.2.2",
|
85
86
|
"gunicorn",
|
86
87
|
"httpcore",
|
87
88
|
"httpx",
|
@@ -159,6 +160,7 @@ pipeline = [
|
|
159
160
|
"unstructured[local-inference,all-docs]"
|
160
161
|
]
|
161
162
|
gcp = [
|
163
|
+
"aiofiles",
|
162
164
|
"anthropic[vertex]",
|
163
165
|
"google-api-python-client",
|
164
166
|
"google-auth-httplib2",
|
@@ -173,7 +175,7 @@ gcp = [
|
|
173
175
|
"google-cloud-pubsub",
|
174
176
|
"google-cloud-discoveryengine>=0.13.4",
|
175
177
|
"google-cloud-texttospeech",
|
176
|
-
"google-genai",
|
178
|
+
"google-genai>=0.2.2",
|
177
179
|
"google-generativeai>=0.8.3",
|
178
180
|
"langchain-google-genai>=2.0.0",
|
179
181
|
"langchain_google_alloydb_pg>=0.2.2",
|
@@ -9,8 +9,9 @@ from ..custom_logging import log
|
|
9
9
|
def get_default_email():
|
10
10
|
|
11
11
|
# https://stackoverflow.com/questions/64234214/how-to-generate-a-blob-signed-url-in-google-cloud-run
|
12
|
-
|
13
|
-
gcs_credentials
|
12
|
+
gcs_credentials, project_id = get_default_creds()
|
13
|
+
if gcs_credentials is None:
|
14
|
+
gcs_credentials, project_id = refresh_credentials()
|
14
15
|
|
15
16
|
if gcs_credentials is None:
|
16
17
|
log.error("Could not refresh the credentials properly.")
|
@@ -3,6 +3,7 @@ from ..gcs import get_bytes_from_gcs
|
|
3
3
|
|
4
4
|
from functools import partial
|
5
5
|
import mimetypes
|
6
|
+
import uuid
|
6
7
|
import asyncio
|
7
8
|
import tempfile
|
8
9
|
import re
|
@@ -11,6 +12,7 @@ import traceback
|
|
11
12
|
try:
|
12
13
|
import google.generativeai as genai
|
13
14
|
from google import genai as genaiv2
|
15
|
+
|
14
16
|
except ImportError:
|
15
17
|
genai = None
|
16
18
|
genaiv2 = None
|
@@ -89,20 +91,16 @@ def sanitize_file(filename):
|
|
89
91
|
|
90
92
|
async def construct_file_content(gs_list, bucket:str, genai_lib=False):
|
91
93
|
"""
|
94
|
+
Thread-safe implementation for processing multiple files concurrently.
|
95
|
+
|
92
96
|
Args:
|
93
97
|
- gs_list: a list of dicts representing files in a bucket
|
94
|
-
- contentType: The content type of the file on GCS
|
95
|
-
- storagePath: The path in the bucket
|
96
|
-
- name: The name of the file
|
97
|
-
- url: The URL of the file that can be used to display the contents
|
98
98
|
- bucket: The bucket the files are in
|
99
|
-
-
|
100
|
-
|
99
|
+
- genai_lib: whether its using the genai SDK
|
101
100
|
"""
|
102
101
|
|
103
102
|
file_list = []
|
104
103
|
for element in gs_list:
|
105
|
-
|
106
104
|
the_mime_type = element.get('contentType')
|
107
105
|
if the_mime_type is None:
|
108
106
|
continue
|
@@ -124,34 +122,42 @@ async def construct_file_content(gs_list, bucket:str, genai_lib=False):
|
|
124
122
|
img_url = f"gs://{bucket}/{file_info['storagePath']}"
|
125
123
|
display_url = file_info.get('url')
|
126
124
|
mime_type = file_info['contentType']
|
127
|
-
name
|
125
|
+
# Generate a unique name for each file to avoid conflicts
|
126
|
+
original_name = sanitize_file(file_info['name'])
|
127
|
+
unique_name = f"{original_name}_{str(uuid.uuid4())[:8]}"
|
128
128
|
display_name = file_info['name']
|
129
|
-
log.info(f"Processing {
|
129
|
+
log.info(f"Processing {unique_name=} {display_name=}")
|
130
|
+
|
130
131
|
try:
|
131
132
|
if not genai_lib:
|
132
|
-
myfile = genai.get_file(
|
133
|
+
myfile = genai.get_file(unique_name)
|
133
134
|
else:
|
134
135
|
client = genaiv2.Client()
|
135
|
-
myfile = client.files.get(name=
|
136
|
+
myfile = client.files.get(name=unique_name)
|
136
137
|
content.append(myfile)
|
137
138
|
content.append(f"You have been given the ability to work with file {display_name=} with {mime_type=} {display_url=}")
|
138
|
-
log.info(f"Found existing genai.get_file {
|
139
|
+
log.info(f"Found existing genai.get_file {unique_name=}")
|
139
140
|
except Exception as e:
|
140
|
-
log.info(f"Not found checking genai.get_file: '{
|
141
|
+
log.info(f"Not found checking genai.get_file: '{unique_name}' {str(e)}")
|
141
142
|
tasks.append(
|
142
143
|
download_gcs_upload_genai(img_url,
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
# Run all tasks in parallel
|
151
|
-
if tasks:
|
152
|
-
task_content = await asyncio.gather(*tasks)
|
153
|
-
content.extend(task_content)
|
144
|
+
mime_type=mime_type,
|
145
|
+
name=unique_name,
|
146
|
+
display_url=display_url,
|
147
|
+
display_name=display_name,
|
148
|
+
genai_lib=genai_lib)
|
149
|
+
)
|
154
150
|
|
151
|
+
# Process files in batches to avoid overwhelming the system
|
152
|
+
content_results = []
|
153
|
+
batch_size = 3 # Process 3 files at a time
|
154
|
+
|
155
|
+
for i in range(0, len(tasks), batch_size):
|
156
|
+
batch = tasks[i:i+batch_size]
|
157
|
+
batch_results = await asyncio.gather(*batch)
|
158
|
+
content_results.extend(batch_results)
|
159
|
+
|
160
|
+
content.extend(content_results)
|
155
161
|
return content
|
156
162
|
|
157
163
|
# Helper function to handle each file download with error handling
|
@@ -169,10 +175,9 @@ async def download_gcs_upload_genai(img_url,
|
|
169
175
|
display_url=None,
|
170
176
|
display_name=None,
|
171
177
|
retries=3, delay=2, genai_lib=False):
|
172
|
-
import aiofiles
|
173
|
-
from google.generativeai.types import file_types
|
174
178
|
"""
|
175
179
|
Downloads and uploads a file with retries in case of failure.
|
180
|
+
Thread-safe implementation using unique file paths.
|
176
181
|
|
177
182
|
Args:
|
178
183
|
- img_url: str The URL of the file to download.
|
@@ -184,9 +189,10 @@ async def download_gcs_upload_genai(img_url,
|
|
184
189
|
Returns:
|
185
190
|
- downloaded_content: The result of the file upload if successful.
|
186
191
|
"""
|
192
|
+
import aiofiles
|
187
193
|
for attempt in range(retries):
|
188
194
|
try:
|
189
|
-
log.info(f"Upload {attempt} for {img_url=}")
|
195
|
+
log.info(f"Upload attempt [{attempt}] for {img_url=}")
|
190
196
|
# Download the file bytes asynchronously
|
191
197
|
file_bytes = await asyncio.to_thread(get_bytes_from_gcs, img_url)
|
192
198
|
if not file_bytes:
|
@@ -200,50 +206,72 @@ async def download_gcs_upload_genai(img_url,
|
|
200
206
|
|
201
207
|
if file_size > 19434343:
|
202
208
|
log.warning(f"File size for {img_url}: {file_size} is too big.")
|
203
|
-
msg =
|
209
|
+
msg = f"The file for {img_url} is too large ({file_size} bytes) to be used directly. Use RAG instead or {display_url=}"
|
204
210
|
return {"role": "user", "parts": [{"text": msg}]}
|
205
211
|
|
206
212
|
extension = mimetypes.guess_extension(mime_type)
|
207
213
|
|
208
|
-
#
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
214
|
+
# Create a unique directory for this upload task
|
215
|
+
unique_id = str(uuid.uuid4())
|
216
|
+
temp_dir = os.path.join(tempfile.gettempdir(), f"upload_{unique_id}")
|
217
|
+
os.makedirs(temp_dir, exist_ok=True)
|
218
|
+
|
219
|
+
# Create a file with unique path
|
220
|
+
file_path = os.path.join(temp_dir, f"file_{unique_id}{extension}")
|
221
|
+
|
222
|
+
log.info(f"Writing file {file_path}")
|
223
|
+
async with aiofiles.open(file_path, 'wb') as f:
|
216
224
|
await f.write(file_bytes)
|
217
225
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
downloaded_content: file_types.File = await asyncio.to_thread(
|
226
|
+
try:
|
227
|
+
if not genai_lib:
|
228
|
+
downloaded_content = await asyncio.to_thread(
|
222
229
|
partial(genai.upload_file, name=name, mime_type=mime_type, display_name=display_name),
|
223
|
-
|
224
|
-
|
230
|
+
file_path
|
231
|
+
)
|
232
|
+
|
233
|
+
# Clean up after successful upload
|
234
|
+
try:
|
235
|
+
os.remove(file_path)
|
236
|
+
os.rmdir(temp_dir)
|
237
|
+
except OSError as e:
|
238
|
+
log.warning(f"Cleanup error (non-critical): {str(e)}")
|
239
|
+
|
225
240
|
return {"role": "user", "parts": [{"file_data": downloaded_content},
|
226
|
-
{"text": f"You have been given the ability to read and work with filename '{display_name
|
227
|
-
|
228
|
-
|
229
|
-
msg = f"Could not upload {sanitized_file} to genai.upload_file: {str(err)} {traceback.format_exc()} {display_url=}"
|
230
|
-
log.error(msg)
|
231
|
-
return {"role": "user", "parts": [{"text": msg}]}
|
232
|
-
else:
|
233
|
-
try:
|
241
|
+
{"text": f"You have been given the ability to read and work with filename '{display_name}' with {mime_type=} {display_url=}"}
|
242
|
+
]}
|
243
|
+
else:
|
234
244
|
client = genaiv2.Client()
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
245
|
+
|
246
|
+
# Use semaphore to limit concurrent uploads
|
247
|
+
async with upload_semaphore:
|
248
|
+
downloaded_content = await asyncio.to_thread(
|
249
|
+
client.files.upload,
|
250
|
+
file=file_path,
|
251
|
+
config=dict(mime_type=mime_type, display_name=display_name)
|
252
|
+
)
|
253
|
+
|
254
|
+
# Clean up after successful upload
|
255
|
+
try:
|
256
|
+
os.remove(file_path)
|
257
|
+
os.rmdir(temp_dir)
|
258
|
+
except OSError as e:
|
259
|
+
log.warning(f"Cleanup error (non-critical): {str(e)}")
|
260
|
+
|
240
261
|
return [downloaded_content,
|
241
|
-
f"You have been given the ability to read and work with filename '{display_name
|
262
|
+
f"You have been given the ability to read and work with filename '{display_name}' with {mime_type=} {display_url=}"]
|
242
263
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
264
|
+
except Exception as err:
|
265
|
+
# Clean up on error
|
266
|
+
try:
|
267
|
+
os.remove(file_path)
|
268
|
+
os.rmdir(temp_dir)
|
269
|
+
except OSError:
|
270
|
+
pass
|
271
|
+
|
272
|
+
msg = f"Could not upload {file_path} to {'genai.upload_file' if not genai_lib else 'genaiv2.client.files.upload'}: {str(err)} {traceback.format_exc()} {display_url=}"
|
273
|
+
log.error(msg)
|
274
|
+
return {"role": "user", "parts": [{"text": msg}]}
|
247
275
|
|
248
276
|
except Exception as err:
|
249
277
|
log.error(f"Error processing file {img_url} {mime_type=} on attempt {attempt + 1}/{retries}: {str(err)}")
|
@@ -255,3 +283,7 @@ async def download_gcs_upload_genai(img_url,
|
|
255
283
|
else:
|
256
284
|
raise err # Raise the error after max retries
|
257
285
|
|
286
|
+
# Add this at the module level
|
287
|
+
# Create a semaphore to limit concurrent uploads
|
288
|
+
upload_semaphore = asyncio.Semaphore(5) # Adjust the value based on your needs
|
289
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: sunholo
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.120.0
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
5
5
|
Author-email: Holosun ApS <multivac@sunholo.com>
|
6
6
|
License: Apache License, Version 2.0
|
@@ -28,6 +28,7 @@ Provides-Extra: test
|
|
28
28
|
Requires-Dist: pytest; extra == "test"
|
29
29
|
Requires-Dist: pytest-cov; extra == "test"
|
30
30
|
Provides-Extra: all
|
31
|
+
Requires-Dist: aiofiles; extra == "all"
|
31
32
|
Requires-Dist: aiohttp; extra == "all"
|
32
33
|
Requires-Dist: anthropic[vertex]; extra == "all"
|
33
34
|
Requires-Dist: asyncpg; extra == "all"
|
@@ -50,7 +51,7 @@ Requires-Dist: google-cloud-pubsub; extra == "all"
|
|
50
51
|
Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "all"
|
51
52
|
Requires-Dist: google-cloud-texttospeech; extra == "all"
|
52
53
|
Requires-Dist: google-generativeai>=0.7.1; extra == "all"
|
53
|
-
Requires-Dist: google-genai; extra == "all"
|
54
|
+
Requires-Dist: google-genai>=0.2.2; extra == "all"
|
54
55
|
Requires-Dist: gunicorn; extra == "all"
|
55
56
|
Requires-Dist: httpcore; extra == "all"
|
56
57
|
Requires-Dist: httpx; extra == "all"
|
@@ -122,6 +123,7 @@ Requires-Dist: pytesseract; extra == "pipeline"
|
|
122
123
|
Requires-Dist: tabulate; extra == "pipeline"
|
123
124
|
Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
|
124
125
|
Provides-Extra: gcp
|
126
|
+
Requires-Dist: aiofiles; extra == "gcp"
|
125
127
|
Requires-Dist: anthropic[vertex]; extra == "gcp"
|
126
128
|
Requires-Dist: google-api-python-client; extra == "gcp"
|
127
129
|
Requires-Dist: google-auth-httplib2; extra == "gcp"
|
@@ -136,7 +138,7 @@ Requires-Dist: google-cloud-logging; extra == "gcp"
|
|
136
138
|
Requires-Dist: google-cloud-pubsub; extra == "gcp"
|
137
139
|
Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "gcp"
|
138
140
|
Requires-Dist: google-cloud-texttospeech; extra == "gcp"
|
139
|
-
Requires-Dist: google-genai; extra == "gcp"
|
141
|
+
Requires-Dist: google-genai>=0.2.2; extra == "gcp"
|
140
142
|
Requires-Dist: google-generativeai>=0.8.3; extra == "gcp"
|
141
143
|
Requires-Dist: langchain-google-genai>=2.0.0; extra == "gcp"
|
142
144
|
Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
|
@@ -6,6 +6,7 @@ ruamel.yaml
|
|
6
6
|
tenacity
|
7
7
|
|
8
8
|
[all]
|
9
|
+
aiofiles
|
9
10
|
aiohttp
|
10
11
|
anthropic[vertex]
|
11
12
|
asyncpg
|
@@ -28,7 +29,7 @@ google-cloud-pubsub
|
|
28
29
|
google-cloud-discoveryengine>=0.13.4
|
29
30
|
google-cloud-texttospeech
|
30
31
|
google-generativeai>=0.7.1
|
31
|
-
google-genai
|
32
|
+
google-genai>=0.2.2
|
32
33
|
gunicorn
|
33
34
|
httpcore
|
34
35
|
httpx
|
@@ -97,6 +98,7 @@ requests
|
|
97
98
|
rich
|
98
99
|
|
99
100
|
[gcp]
|
101
|
+
aiofiles
|
100
102
|
anthropic[vertex]
|
101
103
|
google-api-python-client
|
102
104
|
google-auth-httplib2
|
@@ -111,7 +113,7 @@ google-cloud-logging
|
|
111
113
|
google-cloud-pubsub
|
112
114
|
google-cloud-discoveryengine>=0.13.4
|
113
115
|
google-cloud-texttospeech
|
114
|
-
google-genai
|
116
|
+
google-genai>=0.2.2
|
115
117
|
google-generativeai>=0.8.3
|
116
118
|
langchain-google-genai>=2.0.0
|
117
119
|
langchain_google_alloydb_pg>=0.2.2
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{sunholo-0.119.18 → sunholo-0.120.0}/src/sunholo/discovery_engine/discovery_engine_client.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|