sunholo 0.84.7__py3-none-any.whl → 0.84.9__py3-none-any.whl

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.
@@ -4,7 +4,7 @@ from ..custom_logging import log
4
4
  from ..utils import ConfigManager
5
5
  from .safety import genai_safety
6
6
 
7
- from typing import TYPE_CHECKING
7
+ from typing import TYPE_CHECKING, Union
8
8
 
9
9
  try:
10
10
  import google.generativeai as genai
@@ -24,14 +24,15 @@ class GenAIFunctionProcessor:
24
24
  of function names mapped to their implementations.
25
25
 
26
26
  Attributes:
27
- config (ConfigManager): Configuration manager instance.
27
+ config (ConfigManager): Configuration manager instance. Reach values via self.config within your own construct_tools() method
28
28
  funcs (dict): A dictionary of function names mapped to their implementations.
29
29
 
30
30
  Example usage:
31
+
31
32
  ```python
32
33
  class AlloyDBFunctionProcessor(GenAIFunctionProcessor):
33
34
  def construct_tools(self) -> dict:
34
- ...
35
+ pass
35
36
 
36
37
  config = ConfigManager()
37
38
  alloydb_processor = AlloyDBFunctionProcessor(config)
@@ -58,6 +59,7 @@ class GenAIFunctionProcessor:
58
59
  self.config = config
59
60
  self.funcs = self.construct_tools()
60
61
  self.model_name = config.vacConfig("model") or "gemini-1.5-flash"
62
+ self.last_api_requests_and_responses = []
61
63
  self._validate_functions()
62
64
 
63
65
  def construct_tools(self) -> dict:
@@ -68,7 +70,7 @@ class GenAIFunctionProcessor:
68
70
  function implementations required for the application.
69
71
 
70
72
  Returns:
71
- dict: A dictionary where keys are function names and values are function objects. e.g. {"my_func": my_func}
73
+ dict: A dictionary where keys are function names and values are function objects
72
74
 
73
75
  Raises:
74
76
  NotImplementedError: If the method is not overridden in a subclass.
@@ -90,8 +92,86 @@ class GenAIFunctionProcessor:
90
92
  if not func.__doc__:
91
93
  log.error(f"Function {func_name} is missing a docstring.")
92
94
  raise ValueError(f"Function {func_name} must have a docstring to be used as a genai tool.")
95
+
96
+
97
+ def parse_as_parts(self, api_requests_and_responses=[]):
98
+ if not api_requests_and_responses and not self.last_api_requests_and_responses:
99
+ log.info("No api_requests_and_responses found to parse to parts")
100
+ return None
101
+
102
+ if api_requests_and_responses:
103
+ self.last_api_requests_and_responses = api_requests_and_responses
104
+
105
+ from google.generativeai.protos import Part
106
+
107
+ work_on = api_requests_and_responses or self.last_api_requests_and_responses
108
+ parts = []
109
+ for part in work_on:
110
+ parts.append(
111
+ Part(
112
+ function_response=genai.protos.FunctionResponse(
113
+ name=part[0],
114
+ response={"result": part[2]}
115
+ )
116
+ )
117
+ )
118
+
119
+ return parts
120
+
121
+ def check_function_result(self, function_name, target_value, api_requests_and_responses=[]):
122
+ """
123
+ Checks if a specific function result in the api_requests_and_responses contains a certain value.
93
124
 
94
- def process_funcs(self, full_response, output_parts=True) -> list['Part'] | str:
125
+ Args:
126
+ function_name (str): The name of the function to check.
127
+ target_value: The value to look for in the function result.
128
+ api_requests_and_responses (list, optional): List of function call results to check.
129
+ If not provided, the method will use `self.last_api_requests_and_responses`.
130
+
131
+ Returns:
132
+ bool: True if the target_value is found in the specified function's result, otherwise False.
133
+ """
134
+ if not api_requests_and_responses:
135
+ api_requests_and_responses = self.last_api_requests_and_responses
136
+
137
+ if not api_requests_and_responses:
138
+ log.info("No api_requests_and_responses found to check.")
139
+ return False
140
+
141
+ for part in api_requests_and_responses:
142
+ func_name = part[0]
143
+ result = part[2]
144
+
145
+ if func_name == function_name:
146
+ if isinstance(result, list) and target_value in result:
147
+ log.info(f"Target value '{target_value}' found in the result of function '{function_name}'.")
148
+ return True
149
+ elif result == target_value:
150
+ log.info(f"Target value '{target_value}' found in the result of function '{function_name}'.")
151
+ return True
152
+
153
+ log.info(f"Target value '{target_value}' not found in the result of function '{function_name}'.")
154
+ return False
155
+
156
+ def parse_as_string(self, api_requests_and_responses=[]):
157
+ if not api_requests_and_responses and not self.last_api_requests_and_responses:
158
+ log.info("No api_requests_and_response found to parse to string")
159
+ return None
160
+
161
+ if api_requests_and_responses:
162
+ self.last_api_requests_and_responses = api_requests_and_responses
163
+
164
+ work_on = api_requests_and_responses or self.last_api_requests_and_responses
165
+ strings = []
166
+ for part in work_on:
167
+ strings.append(
168
+ f"function tool {part[0]} was called with arguments: {part[1]} and got this result:\n"
169
+ f"<{part[0]}_result>{part[2]}</{part[0]}_result>"
170
+ )
171
+
172
+ return strings
173
+
174
+ def process_funcs(self, full_response, output_parts=True) -> Union[list['Part'], str]:
95
175
  """
96
176
  Processes the functions based on the full_response from the generative model.
97
177
 
@@ -141,30 +221,28 @@ class GenAIFunctionProcessor:
141
221
  log.error(f"Function {function_name} is not recognized")
142
222
 
143
223
  log.info(f"{api_requests_and_responses=}")
224
+ self.last_api_requests_and_responses = api_requests_and_responses
144
225
 
145
226
  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
227
+ return self.parse_as_parts()
228
+
229
+ return self.parse_as_string()
230
+
231
+ def tool_config_setting(self, mode:str):
232
+ from google.generativeai.types import content_types
157
233
 
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
- )
234
+ fns = list(self.funcs.keys())
164
235
 
165
- return strings
236
+ return content_types.to_tool_config(
237
+ {"function_calling_config": {"mode": mode, "allowed_function_names": fns}}
238
+ )
166
239
 
167
- def get_model(self, system_instruction: str, generation_config=None, model_name: str=None):
240
+ def get_model(
241
+ self,
242
+ system_instruction: str,
243
+ generation_config=None,
244
+ model_name: str=None,
245
+ tool_config: str="auto"):
168
246
  """
169
247
  Constructs and returns the generative AI model configured with the tools.
170
248
 
@@ -175,11 +253,13 @@ class GenAIFunctionProcessor:
175
253
  model_name (str): The name of the model to use.
176
254
  system_instruction (str): Instructions for the AI system.
177
255
  generation_config (dict, optional): Configuration for generation, such as temperature.
256
+ tool_config (str, optional): Configuration for tool behaviour: 'auto' it decides, 'none' no tools, 'any' always use tools
178
257
 
179
258
  Returns:
180
259
  GenerativeModel: An instance of the GenerativeModel configured with the provided tools.
181
260
 
182
261
  Example usage:
262
+
183
263
  ```python
184
264
  alloydb_model = alloydb_processor.get_model(
185
265
  model_name="gemini-1.5-pro",
@@ -200,6 +280,7 @@ class GenAIFunctionProcessor:
200
280
  model = genai.GenerativeModel(
201
281
  model_name=model_name or self.model_name,
202
282
  tools=tools,
283
+ tool_config=self.tool_config_setting(tool_config),
203
284
  generation_config=generation_config,
204
285
  safety_settings=genai_safety(),
205
286
  system_instruction=system_instruction,
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.84.7
3
+ Version: 0.84.9
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.7.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.84.9.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -83,7 +83,7 @@ sunholo/gcs/download_folder.py,sha256=ijJTnS595JqZhBH8iHFErQilMbkuKgL-bnTCMLGuvl
83
83
  sunholo/gcs/download_url.py,sha256=q1NiJSvEhdNrmU5ZJ-sBCMC_J5CxzrajY8LRgdPOV_M,6130
84
84
  sunholo/gcs/metadata.py,sha256=oQLcXi4brsZ74aegWyC1JZmhlaEV270HS5_UWtAYYWE,898
85
85
  sunholo/genai/__init__.py,sha256=o2c17UbgzIDxNKKF8deCLoctNpatAYgm9Cf9XDfpqvg,87
86
- sunholo/genai/process_funcs_cls.py,sha256=h0W767nXrwPesrc9iDEJ1bzesvXeze7YV8U7cASkKdc,8150
86
+ sunholo/genai/process_funcs_cls.py,sha256=22Uf0s8KSiRsi0iZHdI2amj8EW-dzSC4jPY_4SE382I,11615
87
87
  sunholo/genai/safety.py,sha256=mkFDO_BeEgiKjQd9o2I4UxB6XI7a9U-oOFjZ8LGRUC4,1238
88
88
  sunholo/invoke/__init__.py,sha256=bELcqIjzKvaupcIN5OQmDgGx_8jARtH9T6PCe8UgcvE,99
89
89
  sunholo/invoke/async_class.py,sha256=J-qMgarhdi6nPQyOIFM5k0wF7nqr8aJGaz99-Ye6XGQ,3507
@@ -138,9 +138,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
138
138
  sunholo/vertex/memory_tools.py,sha256=q_phxgGX2TG2j2MXNULF2xGzQnQPENwjPN9nZ_A9Gh0,7526
139
139
  sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
140
140
  sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
141
- sunholo-0.84.7.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
142
- sunholo-0.84.7.dist-info/METADATA,sha256=7k9YTlJrqeB25j52O1Qr3kCfTAmu2hy5W_Tn62IepEE,7412
143
- sunholo-0.84.7.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
144
- sunholo-0.84.7.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
145
- sunholo-0.84.7.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
146
- sunholo-0.84.7.dist-info/RECORD,,
141
+ sunholo-0.84.9.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
142
+ sunholo-0.84.9.dist-info/METADATA,sha256=X4CjiNhE4oYZ9_TAe9gm4--W0-WxGaDM27dFe5qNEdE,7412
143
+ sunholo-0.84.9.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
144
+ sunholo-0.84.9.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
145
+ sunholo-0.84.9.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
146
+ sunholo-0.84.9.dist-info/RECORD,,