unique_toolkit 1.14.11__py3-none-any.whl → 1.15.0__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.
@@ -19,7 +19,10 @@ from unique_toolkit._common.endpoint_requestor import (
19
19
  RequestorType,
20
20
  build_requestor,
21
21
  )
22
- from unique_toolkit._common.pydantic_helpers import create_union_model
22
+ from unique_toolkit._common.pydantic_helpers import (
23
+ create_complement_model,
24
+ create_union_model,
25
+ )
23
26
  from unique_toolkit._common.string_utilities import (
24
27
  dict_to_markdown_table,
25
28
  extract_dicts_from_string,
@@ -78,24 +81,67 @@ class HumanVerificationManagerForApiCalling(
78
81
  ]
79
82
  ],
80
83
  requestor_type: RequestorType = RequestorType.REQUESTS,
84
+ environment_payload_params: BaseModel | None = None,
85
+ modifiable_payload_params_model: type[BaseModel] | None = None,
81
86
  **kwargs: dict[str, Any],
82
87
  ):
88
+ """
89
+ Manages human verification for api calling.
90
+
91
+ Args:
92
+ logger: The logger to use for logging.
93
+ operation: The operation to use for the api calling.
94
+ requestor_type: The requestor type to use for the api calling.
95
+ environment_payload_params: The environment payload params to use for the api calling.
96
+ If None, the modifiable params model will be the operation payload model.
97
+ This can be useful for parameters in the payload that should not be modified by the user.
98
+ modifiable_payload_params_model: The modifiable payload params model to use for the api calling.
99
+ If None, a complement model will be created using the operation payload model
100
+ and the environment payload params.
101
+ If provided, it will be used instead of the complement model.
102
+ This is necessary if the modifiable params model is required
103
+ to use custom validators or serializers.
104
+ **kwargs: Additional keyword arguments to pass to the requestor.
105
+ """
83
106
  self._logger = logger
84
107
  self._operation = operation
85
-
108
+ self._environment_payload_params = environment_payload_params
86
109
  # Create internal models for this manager instance
87
110
 
88
- class ConcreteApiCall(BaseModel):
111
+ if self._environment_payload_params is None:
112
+ self._modifiable_payload_params_model = self._operation.payload_model()
113
+ else:
114
+ if modifiable_payload_params_model is None:
115
+ self._modifiable_payload_params_model = create_complement_model(
116
+ model_type_a=self._operation.payload_model(),
117
+ model_type_b=type(self._environment_payload_params),
118
+ )
119
+ else:
120
+ # This is necessary if the modifiable params model is required
121
+ # to use custom validators or serializers.
122
+ self._modifiable_payload_params_model = modifiable_payload_params_model
123
+
124
+ if self._environment_payload_params is not None:
125
+ combined_keys = set(
126
+ self._modifiable_payload_params_model.model_fields.keys()
127
+ ) | set(type(self._environment_payload_params).model_fields.keys())
128
+ payload_keys = set(self._operation.payload_model().model_fields.keys())
129
+ if not payload_keys.issubset(combined_keys):
130
+ raise ValueError(
131
+ "The modifiable params model + the environment parameters do not have all the keys of the operation payload model."
132
+ )
133
+
134
+ class VerificationModel(BaseModel):
89
135
  confirmation: HumanConfirmation
90
- payload: self._operation.payload_model() # type: ignore
136
+ modifiable_params: self._modifiable_payload_params_model # type: ignore
91
137
 
92
- self._api_call_model = ConcreteApiCall
138
+ self._verification_model = VerificationModel
93
139
 
140
+ self._requestor_type = requestor_type
94
141
  self._combined_params_model = create_union_model(
95
142
  model_type_a=self._operation.path_params_model(),
96
143
  model_type_b=self._operation.payload_model(),
97
144
  )
98
- self._requestor_type = requestor_type
99
145
  self._requestor = build_requestor(
100
146
  requestor_type=requestor_type,
101
147
  operation_type=operation,
@@ -104,7 +150,10 @@ class HumanVerificationManagerForApiCalling(
104
150
  )
105
151
 
106
152
  def detect_api_calls_from_user_message(
107
- self, *, last_assistant_message: ChatMessage, user_message: str
153
+ self,
154
+ *,
155
+ last_assistant_message: ChatMessage,
156
+ user_message: str,
108
157
  ) -> PayloadType | None:
109
158
  user_message_dicts = extract_dicts_from_string(user_message)
110
159
  if len(user_message_dicts) == 0:
@@ -114,13 +163,20 @@ class HumanVerificationManagerForApiCalling(
114
163
  for user_message_dict in user_message_dicts:
115
164
  try:
116
165
  # Convert dict to payload model first, then create payload
117
- api_call = self._api_call_model.model_validate(
166
+ verfication_data = self._verification_model.model_validate(
118
167
  user_message_dict, by_alias=True, by_name=True
119
168
  )
120
169
  if self._verify_human_verification(
121
- api_call.confirmation, last_assistant_message
170
+ verfication_data.confirmation, last_assistant_message
122
171
  ):
123
- return api_call.payload
172
+ payload_dict = verfication_data.modifiable_params.model_dump()
173
+ if self._environment_payload_params is not None:
174
+ payload_dict.update(
175
+ self._environment_payload_params.model_dump()
176
+ )
177
+
178
+ return self._operation.payload_model().model_validate(payload_dict)
179
+
124
180
  except Exception as e:
125
181
  self._logger.error(f"Error detecting api calls from user message: {e}")
126
182
 
@@ -141,11 +197,27 @@ class HumanVerificationManagerForApiCalling(
141
197
  return confirmation.payload_hash in last_assistant_message.content
142
198
 
143
199
  def _create_next_user_message(self, payload: PayloadType) -> str:
144
- api_call = self._api_call_model(
145
- payload=payload,
200
+ # Extract only the modifiable fields from the payload
201
+ payload_dict = payload.model_dump()
202
+ if self._environment_payload_params is not None:
203
+ # Remove environment params from payload to avoid validation errors
204
+ environment_fields = set(
205
+ type(self._environment_payload_params).model_fields.keys()
206
+ )
207
+ modifiable_dict = {
208
+ k: v for k, v in payload_dict.items() if k not in environment_fields
209
+ }
210
+ else:
211
+ modifiable_dict = payload_dict
212
+
213
+ modifiable_params = self._modifiable_payload_params_model.model_validate(
214
+ modifiable_dict
215
+ )
216
+ api_call = self._verification_model(
217
+ modifiable_params=modifiable_params,
146
218
  confirmation=HumanConfirmation(
147
219
  payload_hash=hashlib.sha256(
148
- payload.model_dump_json().encode()
220
+ modifiable_params.model_dump_json().encode()
149
221
  ).hexdigest(),
150
222
  time_stamp=datetime.now(),
151
223
  ),
@@ -168,6 +240,14 @@ class HumanVerificationManagerForApiCalling(
168
240
  path_params: PathParamsType,
169
241
  payload: PayloadType,
170
242
  ) -> ResponseType:
243
+ """
244
+ Call the api with the given path params, payload and secured payload params.
245
+
246
+ The `secured payload params` are params that are enforced by the application.
247
+ It should generally be not possible for the user to adapt those but here we
248
+ ensure that the application has the last word.
249
+
250
+ """
171
251
  params = path_params.model_dump()
172
252
  params.update(payload.model_dump())
173
253
 
@@ -217,8 +297,8 @@ if __name__ == "__main__":
217
297
 
218
298
  payload = GetUserRequestBody(include_profile=True)
219
299
 
220
- api_call = human_verification_manager._api_call_model(
221
- payload=payload,
300
+ api_call = human_verification_manager._verification_model(
301
+ modifiable_params=payload,
222
302
  confirmation=HumanConfirmation(
223
303
  payload_hash=hashlib.sha256(payload.model_dump_json().encode()).hexdigest(),
224
304
  time_stamp=datetime.now(),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 1.14.11
3
+ Version: 1.15.0
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -118,6 +118,9 @@ All notable changes to this project will be documented in this file.
118
118
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
119
119
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
120
120
 
121
+ ## [1.15.0] - 2025-10-15
122
+ - Enable to distinguish between environment and modifiable payload parameters in human verification
123
+
121
124
  ## [1.14.11] - 2025-10-13
122
125
  - Introduce testing guidelines for AI
123
126
  - Add AI tests to `tool_config` and `tool_factory.py`
@@ -1,7 +1,7 @@
1
1
  unique_toolkit/__init__.py,sha256=qrQ0kgAZnmGR6-UpWOpAL4yd-2ic5Jjwh6s8et-7ZTc,1372
2
2
  unique_toolkit/_common/_base_service.py,sha256=S8H0rAebx7GsOldA7xInLp3aQJt9yEPDQdsGSFRJsGg,276
3
3
  unique_toolkit/_common/_time_utils.py,sha256=ztmTovTvr-3w71Ns2VwXC65OKUUh-sQlzbHdKTQWm-w,135
4
- unique_toolkit/_common/api_calling/human_verification_manager.py,sha256=wgK0hefTh3pdrs8kH26Pba46ROQoFihEhT4r6h189wo,7819
4
+ unique_toolkit/_common/api_calling/human_verification_manager.py,sha256=ZgWThDHdTNFmgNdE4dwR7L7qPV73nSe5wOLpcB1QbWM,11919
5
5
  unique_toolkit/_common/base_model_type_attribute.py,sha256=7rzVqjXa0deYEixeo_pJSJcQ7nKXpWK_UGpOiEH3yZY,10382
6
6
  unique_toolkit/_common/chunk_relevancy_sorter/config.py,sha256=tHETuMIC4CA_TPwU0oaHbckaKhvMFMYdO_d4lNRKnRc,1806
7
7
  unique_toolkit/_common/chunk_relevancy_sorter/exception.py,sha256=1mY4zjbvnXsd5oIxwiVsma09bS2XRnHrxW8KJBGtgCM,126
@@ -152,7 +152,7 @@ unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBu
152
152
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
153
  unique_toolkit/smart_rules/compile.py,sha256=Ozhh70qCn2yOzRWr9d8WmJeTo7AQurwd3tStgBMPFLA,1246
154
154
  unique_toolkit/test_utilities/events.py,sha256=_mwV2bs5iLjxS1ynDCjaIq-gjjKhXYCK-iy3dRfvO3g,6410
155
- unique_toolkit-1.14.11.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
156
- unique_toolkit-1.14.11.dist-info/METADATA,sha256=0Vy2yKAM4d6rUAmlhOQT4Jx4Ssk3QLCxbdEnkiR-Hz8,37225
157
- unique_toolkit-1.14.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
158
- unique_toolkit-1.14.11.dist-info/RECORD,,
155
+ unique_toolkit-1.15.0.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
156
+ unique_toolkit-1.15.0.dist-info/METADATA,sha256=AceGAlpsF4t7o7rfBk4jINF5iqJucZD3uyouIAm6y0k,37350
157
+ unique_toolkit-1.15.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
158
+ unique_toolkit-1.15.0.dist-info/RECORD,,