sunholo 0.84.2__tar.gz → 0.84.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. {sunholo-0.84.2 → sunholo-0.84.5}/PKG-INFO +2 -2
  2. {sunholo-0.84.2 → sunholo-0.84.5}/setup.py +1 -1
  3. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/__init__.py +2 -0
  4. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/alloydb_client.py +5 -3
  5. sunholo-0.84.5/sunholo/genai/process_funcs_cls.py +208 -0
  6. sunholo-0.84.5/sunholo/genai/safety.py +32 -0
  7. sunholo-0.84.5/sunholo/patches/langchain/__init__.py +0 -0
  8. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/parsers.py +8 -3
  9. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo.egg-info/PKG-INFO +2 -2
  10. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo.egg-info/SOURCES.txt +3 -0
  11. {sunholo-0.84.2 → sunholo-0.84.5}/LICENSE.txt +0 -0
  12. {sunholo-0.84.2 → sunholo-0.84.5}/MANIFEST.in +0 -0
  13. {sunholo-0.84.2 → sunholo-0.84.5}/README.md +0 -0
  14. {sunholo-0.84.2 → sunholo-0.84.5}/setup.cfg +0 -0
  15. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/__init__.py +0 -0
  16. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/chat_history.py +0 -0
  17. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/dispatch_to_qa.py +0 -0
  18. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/fastapi/__init__.py +0 -0
  19. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/fastapi/base.py +0 -0
  20. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/fastapi/qna_routes.py +0 -0
  21. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/flask/__init__.py +0 -0
  22. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/flask/base.py +0 -0
  23. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/flask/qna_routes.py +0 -0
  24. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/flask/vac_routes.py +0 -0
  25. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/langserve.py +0 -0
  26. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/pubsub.py +0 -0
  27. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/route.py +0 -0
  28. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/special_commands.py +0 -0
  29. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/agents/swagger.py +0 -0
  30. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/archive/__init__.py +0 -0
  31. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/archive/archive.py +0 -0
  32. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/auth/__init__.py +0 -0
  33. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/auth/gcloud.py +0 -0
  34. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/auth/refresh.py +0 -0
  35. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/auth/run.py +0 -0
  36. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/azure/__init__.py +0 -0
  37. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/azure/auth.py +0 -0
  38. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/azure/blobs.py +0 -0
  39. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/azure/event_grid.py +0 -0
  40. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/bots/__init__.py +0 -0
  41. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/bots/discord.py +0 -0
  42. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/bots/github_webhook.py +0 -0
  43. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/bots/webapp.py +0 -0
  44. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/__init__.py +0 -0
  45. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/azure.py +0 -0
  46. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/doc_handling.py +0 -0
  47. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/encode_metadata.py +0 -0
  48. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/images.py +0 -0
  49. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/loaders.py +0 -0
  50. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/message_data.py +0 -0
  51. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/pdfs.py +0 -0
  52. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/process_chunker_data.py +0 -0
  53. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/publish.py +0 -0
  54. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/pubsub.py +0 -0
  55. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/chunker/splitter.py +0 -0
  56. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/__init__.py +0 -0
  57. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/chat_vac.py +0 -0
  58. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/cli.py +0 -0
  59. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/cli_init.py +0 -0
  60. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/configs.py +0 -0
  61. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/deploy.py +0 -0
  62. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/embedder.py +0 -0
  63. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/merge_texts.py +0 -0
  64. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/run_proxy.py +0 -0
  65. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/sun_rich.py +0 -0
  66. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/swagger.py +0 -0
  67. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/cli/vertex.py +0 -0
  68. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/components/__init__.py +0 -0
  69. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/components/llm.py +0 -0
  70. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/components/retriever.py +0 -0
  71. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/components/vectorstore.py +0 -0
  72. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/custom_logging.py +0 -0
  73. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/__init__.py +0 -0
  74. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/alloydb.py +0 -0
  75. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/database.py +0 -0
  76. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/lancedb.py +0 -0
  77. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/sql/sb/create_function.sql +0 -0
  78. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/sql/sb/create_function_time.sql +0 -0
  79. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/sql/sb/create_table.sql +0 -0
  80. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  81. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/sql/sb/return_sources.sql +0 -0
  82. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/sql/sb/setup.sql +0 -0
  83. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/static_dbs.py +0 -0
  84. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/database/uuid.py +0 -0
  85. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/discovery_engine/__init__.py +0 -0
  86. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/discovery_engine/chunker_handler.py +0 -0
  87. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/discovery_engine/create_new.py +0 -0
  88. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  89. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  90. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/embedder/__init__.py +0 -0
  91. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/embedder/embed_chunk.py +0 -0
  92. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/gcs/__init__.py +0 -0
  93. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/gcs/add_file.py +0 -0
  94. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/gcs/download_folder.py +0 -0
  95. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/gcs/download_url.py +0 -0
  96. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/gcs/metadata.py +0 -0
  97. {sunholo-0.84.2/sunholo/langfuse → sunholo-0.84.5/sunholo/genai}/__init__.py +0 -0
  98. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/invoke/__init__.py +0 -0
  99. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/invoke/async_class.py +0 -0
  100. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/invoke/direct_vac_func.py +0 -0
  101. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/invoke/invoke_vac_utils.py +0 -0
  102. {sunholo-0.84.2/sunholo/lookup → sunholo-0.84.5/sunholo/langfuse}/__init__.py +0 -0
  103. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/langfuse/callback.py +0 -0
  104. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/langfuse/prompts.py +0 -0
  105. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/llamaindex/__init__.py +0 -0
  106. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/llamaindex/get_files.py +0 -0
  107. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/llamaindex/import_files.py +0 -0
  108. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/llamaindex/llamaindex_class.py +0 -0
  109. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/llamaindex/user_history.py +0 -0
  110. {sunholo-0.84.2/sunholo/patches → sunholo-0.84.5/sunholo/lookup}/__init__.py +0 -0
  111. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/lookup/model_lookup.yaml +0 -0
  112. {sunholo-0.84.2/sunholo/patches/langchain → sunholo-0.84.5/sunholo/patches}/__init__.py +0 -0
  113. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/patches/langchain/lancedb.py +0 -0
  114. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/patches/langchain/vertexai.py +0 -0
  115. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/pubsub/__init__.py +0 -0
  116. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/pubsub/process_pubsub.py +0 -0
  117. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/pubsub/pubsub_manager.py +0 -0
  118. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/qna/__init__.py +0 -0
  119. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/qna/parsers.py +0 -0
  120. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/qna/retry.py +0 -0
  121. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/streaming/__init__.py +0 -0
  122. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/streaming/content_buffer.py +0 -0
  123. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/streaming/langserve.py +0 -0
  124. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/streaming/stream_lookup.py +0 -0
  125. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/streaming/streaming.py +0 -0
  126. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/summarise/__init__.py +0 -0
  127. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/summarise/summarise.py +0 -0
  128. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/tools/__init__.py +0 -0
  129. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/tools/web_browser.py +0 -0
  130. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/__init__.py +0 -0
  131. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/api_key.py +0 -0
  132. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/big_context.py +0 -0
  133. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/config.py +0 -0
  134. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/config_class.py +0 -0
  135. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/config_schema.py +0 -0
  136. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/gcp.py +0 -0
  137. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/gcp_project.py +0 -0
  138. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/timedelta.py +0 -0
  139. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/user_ids.py +0 -0
  140. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/utils/version.py +0 -0
  141. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/__init__.py +0 -0
  142. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/extensions_call.py +0 -0
  143. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/extensions_class.py +0 -0
  144. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/genai_functions.py +0 -0
  145. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/init.py +0 -0
  146. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/memory_tools.py +0 -0
  147. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/safety.py +0 -0
  148. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo/vertex/type_dict_to_json.py +0 -0
  149. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo.egg-info/dependency_links.txt +0 -0
  150. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo.egg-info/entry_points.txt +0 -0
  151. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo.egg-info/requires.txt +0 -0
  152. {sunholo-0.84.2 → sunholo-0.84.5}/sunholo.egg-info/top_level.txt +0 -0
  153. {sunholo-0.84.2 → sunholo-0.84.5}/tests/test_chat_history.py +0 -0
  154. {sunholo-0.84.2 → sunholo-0.84.5}/tests/test_config.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.84.2
3
+ Version: 0.84.5
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.84.2.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.84.5.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -1,7 +1,7 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
3
  # Define your base version
4
- version = '0.84.2'
4
+ version = '0.84.5'
5
5
 
6
6
  setup(
7
7
  name='sunholo',
@@ -9,6 +9,7 @@ from . import database
9
9
  from . import discovery_engine
10
10
  from . import embedder
11
11
  from . import gcs
12
+ from . import genai
12
13
  from . import invoke
13
14
  from . import langfuse
14
15
  from . import llamaindex
@@ -34,6 +35,7 @@ __all__ = ['agents',
34
35
  'discovery_engine',
35
36
  'embedder',
36
37
  'gcs',
38
+ 'genai',
37
39
  'invoke',
38
40
  'langfuse',
39
41
  'llamaindex',
@@ -71,7 +71,9 @@ class AlloyDBClient:
71
71
  if ALLOYDB_DB is None and alloydb_config.get("database") is None:
72
72
  log.warning("Could not locate ALLOYDB_DB environment variable or 'alloydb_config.database'")
73
73
 
74
- self.database = alloydb_config.get("database") or ALLOYDB_DB
74
+ self.database = alloydb_config.get("database") or ALLOYDB_DB or db
75
+ if not self.database:
76
+ raise ValueError("Could not derive a database to query")
75
77
 
76
78
  self.user = user
77
79
  self.password = password
@@ -212,8 +214,8 @@ class AlloyDBClient:
212
214
  doc_id = generate_uuid_from_object_id(source)
213
215
 
214
216
  query = f"""
215
- SELECT *
216
- FROM {table_name}
217
+ SELECT page_content, source, langchain_metadata, images_gsurls, doc_id::text as doc_id
218
+ FROM "{table_name}"
217
219
  WHERE doc_id = '{doc_id}'
218
220
  LIMIT 1;
219
221
  """
@@ -0,0 +1,208 @@
1
+ import traceback
2
+
3
+ from ..custom_logging import log
4
+ from ..utils import ConfigManager
5
+ from .safety import genai_safety
6
+
7
+ from typing import TYPE_CHECKING
8
+
9
+ try:
10
+ import google.generativeai as genai
11
+ except ImportError:
12
+ genai = None
13
+
14
+ if TYPE_CHECKING:
15
+ from google.generativeai.protos import Part
16
+
17
+ class GenAIFunctionProcessor:
18
+ """
19
+ A generic class for processing function calls from google.generativeai function calling models.
20
+
21
+ This class provides a framework for handling multiple function calls in responses
22
+ from generative AI systems. Users of this class should subclass it and provide
23
+ their own implementation of the `construct_tools` method, which returns a dictionary
24
+ of function names mapped to their implementations.
25
+
26
+ Attributes:
27
+ config (ConfigManager): Configuration manager instance.
28
+ funcs (dict): A dictionary of function names mapped to their implementations.
29
+
30
+ Example usage:
31
+ # Subclassing GenAIFunctionProcessor for a specific application (e.g., AlloyDB)
32
+ class AlloyDBFunctionProcessor(GenAIFunctionProcessor):
33
+ def construct_tools(self) -> dict:
34
+ # Implement function mapping specific to AlloyDB
35
+ ...
36
+
37
+ # Creating an instance of the subclass and using it
38
+ config = ConfigManager()
39
+ alloydb_processor = AlloyDBFunctionProcessor(config)
40
+
41
+ # Processing functions based on a generative AI response
42
+ results = alloydb_processor.process_funcs(full_response)
43
+
44
+ # Getting the configured model
45
+ alloydb_model = alloydb_processor.get_model(
46
+ model_name="gemini-1.5-pro",
47
+ system_instruction="You are a helpful AlloyDB agent that helps users search and extract documents from the database."
48
+ )
49
+ """
50
+
51
+ def __init__(self, config: ConfigManager):
52
+ """
53
+ Initializes the GenAIFunctionProcessor with the given configuration.
54
+
55
+ Args:
56
+ config (ConfigManager): The configuration manager instance.
57
+ """
58
+ if not genai:
59
+ raise ImportError("import google.generativeai as genai is required, import via `pip install sunholo[gcp]`")
60
+
61
+ self.config = config
62
+ self.funcs = self.construct_tools()
63
+ self._validate_functions()
64
+
65
+ def construct_tools(self) -> dict:
66
+ """
67
+ Constructs a dictionary of tools (functions) specific to the application.
68
+
69
+ This method should be overridden in subclasses to provide the specific
70
+ function implementations required for the application.
71
+
72
+ Returns:
73
+ dict: A dictionary where keys are function names and values are function objects. e.g. {"my_func": my_func}
74
+
75
+ Raises:
76
+ NotImplementedError: If the method is not overridden in a subclass.
77
+ """
78
+ raise NotImplementedError("Subclasses must implement this method to return a dictionary of functions.")
79
+
80
+ def _validate_functions(self):
81
+ """
82
+ Validates that all functions in the `funcs` dictionary have docstrings.
83
+
84
+ This method checks each function in the `funcs` dictionary to ensure it has
85
+ a docstring. If a function is missing a docstring, an error is logged, and
86
+ a `ValueError` is raised.
87
+
88
+ Raises:
89
+ ValueError: If any function is missing a docstring.
90
+ """
91
+ for func_name, func in self.funcs.items():
92
+ if not func.__doc__:
93
+ log.error(f"Function {func_name} is missing a docstring.")
94
+ raise ValueError(f"Function {func_name} must have a docstring to be used as a genai tool.")
95
+
96
+ def process_funcs(self, full_response, output_parts=True) -> list[Part] | str:
97
+ """
98
+ Processes the functions based on the full_response from the generative model.
99
+
100
+ This method iterates through each part of the response, extracts function
101
+ calls and their parameters, and executes the corresponding functions defined
102
+ in the `funcs` dictionary.
103
+
104
+ Args:
105
+ full_response: The response object containing function calls.
106
+ output_parts (bool): Indicates whether to return structured parts or plain strings.
107
+
108
+ Returns:
109
+ list[Part] | str: A list of Part objects or a formatted string with the results.
110
+
111
+ Example usage:
112
+ results = alloydb_processor.process_funcs(full_response)
113
+ """
114
+ api_requests_and_responses = []
115
+
116
+ # Loop through each part in the response to handle multiple function calls
117
+ #TODO: async
118
+ for part in full_response.candidates[0].content.parts:
119
+ if fn := part.function_call:
120
+ # Extract parameters for the function call
121
+ function_name = fn.name
122
+ params = {key: val for key, val in fn.args.items()}
123
+ log.info(f"Executing {function_name} with params {params}")
124
+
125
+ # Check if the function is in our dictionary of available functions
126
+ if function_name in self.funcs:
127
+ try:
128
+ # Execute the function with the provided parameters
129
+ result = self.funcs[function_name](**params)
130
+ log.info(f"Got result from {function_name}: {result}")
131
+ except Exception as err:
132
+ error_message = f"Error in {function_name}: {str(err)}"
133
+ traceback_details = traceback.format_exc()
134
+ log.warning(f"{error_message}\nTraceback: {traceback_details}")
135
+ result = [f"{error_message}\n{traceback_details}"]
136
+
137
+ api_requests_and_responses.append(
138
+ [function_name, params, result]
139
+ )
140
+ else:
141
+ log.error(f"Function {function_name} is not recognized")
142
+
143
+ log.info(f"{api_requests_and_responses=}")
144
+
145
+ if output_parts:
146
+ parts = []
147
+ for part in api_requests_and_responses:
148
+ parts.append(
149
+ Part(
150
+ function_response=genai.protos.FunctionResponse(
151
+ name=part[0],
152
+ response={"result": part[2]}
153
+ )
154
+ )
155
+ )
156
+ return parts
157
+
158
+ strings = []
159
+ for part in api_requests_and_responses:
160
+ strings.append(
161
+ f"function tool {part[0]} was called with arguments: {part[1]} and got this result:\n"
162
+ f"<{part[0]}_result>{part[2]}</{part[0]}_result>"
163
+ )
164
+
165
+ return strings
166
+
167
+ def get_model(self, model_name: str, system_instruction: str, generation_config=None):
168
+ """
169
+ Constructs and returns the generative AI model configured with the tools.
170
+
171
+ This method creates a generative AI model using the tools defined in the
172
+ `funcs` dictionary and the provided configuration options.
173
+
174
+ Args:
175
+ model_name (str): The name of the model to use.
176
+ system_instruction (str): Instructions for the AI system.
177
+ generation_config (dict, optional): Configuration for generation, such as temperature.
178
+
179
+ Returns:
180
+ GenerativeModel: An instance of the GenerativeModel configured with the provided tools.
181
+
182
+ Example usage:
183
+ alloydb_model = alloydb_processor.get_model(
184
+ model_name="gemini-1.5-pro",
185
+ system_instruction="You are a helpful AlloyDB agent that helps users search and extract documents from the database."
186
+ )
187
+ """
188
+ if generation_config is None:
189
+ generation_config = {
190
+ "temperature": 0.1,
191
+ "max_output_tokens": 4000,
192
+ }
193
+
194
+ # Extract the functions from the dictionary to pass into the model
195
+ tools = list(self.funcs.values())
196
+
197
+ try:
198
+ model = genai.GenerativeModel(
199
+ model_name=model_name,
200
+ tools=tools,
201
+ generation_config=generation_config,
202
+ safety_settings=genai_safety(),
203
+ system_instruction=system_instruction,
204
+ )
205
+ return model
206
+ except Exception as err:
207
+ log.error(f"Error initializing model: {str(err)}")
208
+ return None
@@ -0,0 +1,32 @@
1
+
2
+ def genai_safety(threshold: str = "BLOCK_ONLY_HIGH"):
3
+ """
4
+ BLOCK_ONLY_HIGH - block when high probability of unsafe content is detected
5
+ BLOCK_MEDIUM_AND_ABOVE - block when medium or high probability of content is detected
6
+ BLOCK_LOW_AND_ABOVE - block when low, medium, or high probability of unsafe content is detected
7
+ BLOCK_NONE - no block, but need to be on an allow list to use
8
+ """
9
+ from google.generativeai.types import (
10
+ HarmCategory,
11
+ HarmBlockThreshold
12
+ )
13
+
14
+ if threshold == 'BLOCK_ONLY_HIGH':
15
+ thresh = HarmBlockThreshold.BLOCK_ONLY_HIGH
16
+ elif threshold == 'BLOCK_MEDIUM_AND_ABOVE':
17
+ thresh = HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE
18
+ elif threshold == 'BLOCK_LOW_AND_ABOVE':
19
+ thresh = HarmBlockThreshold.BLOCK_LOW_AND_ABOVE
20
+ elif threshold == 'BLOCK_NONE':
21
+ thresh = HarmBlockThreshold.BLOCK_NONE
22
+ else:
23
+ raise ValueError("Invalid threshold")
24
+
25
+ safety_settings = {
26
+ HarmCategory.HARM_CATEGORY_HARASSMENT: thresh,
27
+ HarmCategory.HARM_CATEGORY_HATE_SPEECH: thresh,
28
+ HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: thresh,
29
+ HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: thresh,
30
+ }
31
+
32
+ return safety_settings
File without changes
@@ -181,9 +181,14 @@ def escape_braces(text):
181
181
  Returns:
182
182
  str: The modified string with single braces converted to double braces.
183
183
  """
184
- # Replace single braces with double braces
185
- text = re.sub(r'(?<!{){(?!{)', '{{', text) # Replace '{' with '{{' if not already double braced
186
- text = re.sub(r'(?<!})}(?!})', '}}', text) # Replace '}' with '}}' if not already double braced
184
+ # First, handle cases where there might be a mix of braces
185
+ # Replace all `{` that are not followed by another `{` with `{{`
186
+ text = re.sub(r'(?<!{){(?!{)', '{{', text)
187
+
188
+ # Replace all `}` that are not preceded by another `}` with `}}`
189
+ text = re.sub(r'(?<!})}(?!})', '}}', text)
190
+
191
+ # After escaping single braces, return the modified text
187
192
  return text
188
193
 
189
194
  def get_clean_website_name(url: str):
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.84.2
3
+ Version: 0.84.5
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.84.2.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.84.5.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -93,6 +93,9 @@ sunholo/gcs/add_file.py
93
93
  sunholo/gcs/download_folder.py
94
94
  sunholo/gcs/download_url.py
95
95
  sunholo/gcs/metadata.py
96
+ sunholo/genai/__init__.py
97
+ sunholo/genai/process_funcs_cls.py
98
+ sunholo/genai/safety.py
96
99
  sunholo/invoke/__init__.py
97
100
  sunholo/invoke/async_class.py
98
101
  sunholo/invoke/direct_vac_func.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