osbot-utils 2.37.0__py3-none-any.whl → 2.39.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.
@@ -10,7 +10,7 @@ class LLM_Request__Execute(Type_Safe):
10
10
  llm_cache : LLM_Request__Cache
11
11
  llm_api : API__LLM__Open_AI
12
12
  use_cache : bool = True
13
- request_builder: LLM_Request__Builder
13
+ request_builder: LLM_Request__Builder # todo: fix the use of LLM_Request__Builder since it not good when we when overwrite it at self.request_builder.llm_request_data = llm_request.request_data
14
14
 
15
15
  @type_safe
16
16
  def execute(self, llm_request: Schema__LLM_Request) -> Schema__LLM_Response:
@@ -26,6 +26,6 @@ class LLM_Request__Execute(Type_Safe):
26
26
  llm_response = Schema__LLM_Response(response_data=response_data) # Create response object
27
27
 
28
28
  if self.use_cache: # Cache the response if enabled
29
- self.llm_cache.add(llm_request, llm_response)
29
+ self.llm_cache.add(request=llm_request, response=llm_response, payload=llm_payload)
30
30
 
31
31
  return llm_response
@@ -1,10 +1,11 @@
1
1
  from typing import Dict, Any, Type
2
2
  from osbot_utils.helpers.llms.actions.Type_Safe__Schema_For__LLMs import Type_Safe__Schema_For__LLMs
3
+ from osbot_utils.helpers.llms.schemas.Schema__LLM_Request import Schema__LLM_Request
3
4
  from osbot_utils.helpers.llms.schemas.Schema__LLM_Request__Data import Schema__LLM_Request__Data
4
5
  from osbot_utils.helpers.llms.schemas.Schema__LLM_Request__Function_Call import Schema__LLM_Request__Function_Call
5
6
  from osbot_utils.helpers.llms.schemas.Schema__LLM_Request__Message__Content import Schema__LLM_Request__Message__Content
6
7
  from osbot_utils.helpers.llms.schemas.Schema__LLM_Request__Message__Role import Schema__LLM_Request__Message__Role
7
- from osbot_utils.helpers.safe_str.Safe_Str__Text import Safe_Str__Text
8
+ from osbot_utils.helpers.safe_str.Safe_Str__Text import Safe_Str__Text
8
9
  from osbot_utils.type_safe.Type_Safe import Type_Safe
9
10
  from osbot_utils.type_safe.decorators.type_safe import type_safe
10
11
 
@@ -25,6 +26,9 @@ class LLM_Request__Builder(Type_Safe):
25
26
  def add_message__system (self, content : str = None): return self.add_message(role=Schema__LLM_Request__Message__Role.SYSTEM , content=content)
26
27
  def add_message__user (self, content : str = None): return self.add_message(role=Schema__LLM_Request__Message__Role.USER , content=content)
27
28
 
29
+ def llm_request(self) -> Schema__LLM_Request:
30
+ return Schema__LLM_Request(request_data=self.llm_request_data)
31
+
28
32
  @type_safe
29
33
  def set__function_call(self, parameters : Type[Type_Safe],
30
34
  function_name : str,
@@ -10,7 +10,7 @@ class LLM_Request__Builder__Open_AI(LLM_Request__Builder):
10
10
  "messages" : [{"role" : msg.role.value, "content": msg.content} for msg in self.llm_request_data.messages]}
11
11
  if self.llm_request_data.function_call:
12
12
  schema = self.schema_generator.export(self.llm_request_data.function_call.parameters)
13
- schema["additionalProperties"] = False # needs to be False when using structured outputs
13
+ self.add_additional_properties_to_schema(schema)
14
14
  payload["response_format" ] = { "type" : "json_schema",
15
15
  "json_schema": { "name" : self.llm_request_data.function_call.function_name,
16
16
  "schema": schema ,
@@ -22,6 +22,18 @@ class LLM_Request__Builder__Open_AI(LLM_Request__Builder):
22
22
 
23
23
  return payload
24
24
 
25
+ def add_additional_properties_to_schema(self, schema: dict) -> dict: # Recursively ensures every nested object in the schema has "additionalProperties": False.
26
+ if schema.get("type") == "object":
27
+ schema["additionalProperties"] = False
28
+ for prop_schema in schema.get("properties", {}).values():
29
+ self.add_additional_properties_to_schema(prop_schema)
30
+
31
+ elif schema.get("type") == "array":
32
+ items_schema = schema.get("items", {})
33
+ self.add_additional_properties_to_schema(items_schema)
34
+
35
+ return schema
36
+
25
37
  # @type_safe
26
38
  # def build_request_with_json_mode(self, request: Schema__LLM_Request
27
39
  # ) -> Dict[str, Any]:
@@ -25,14 +25,16 @@ class LLM_Request__Cache(Type_Safe):
25
25
  return Safe_Str__Hash(hash_value)
26
26
 
27
27
  @type_safe
28
- def add(self, request : Schema__LLM_Request , # Request to cache
29
- response : Schema__LLM_Response # Response to store
28
+ def add(self, request : Schema__LLM_Request , # Request to cache
29
+ response : Schema__LLM_Response, # Response to store
30
+ payload : dict # Payload to store
30
31
  ) -> Obj_Id: # returns cache_id
31
32
 
32
33
  hash_request = self.compute_request_hash (request) # calculate request hash
33
34
  cache_entry = Schema__LLM_Response__Cache(cache_id = Obj_Id() , # Create a cache entry
34
35
  llm_request = request ,
35
36
  llm_response = response ,
37
+ llm_payload = payload ,
36
38
  hash__request = hash_request )
37
39
  cache_id = cache_entry.cache_id
38
40
 
@@ -169,12 +169,13 @@ class LLM_Request__Cache__File_System(LLM_Request__Cache):
169
169
  return path
170
170
 
171
171
  @type_safe
172
- def add(self, request : Schema__LLM_Request,
172
+ def add(self, request : Schema__LLM_Request ,
173
173
  response : Schema__LLM_Response,
174
+ payload : dict ,
174
175
  now : datetime = None
175
176
  ) -> Obj_Id: # Save an LLM request/response pair using temporal organization.
176
177
 
177
- cache_id = super().add(request, response) # First use standard add() to handle in-memory caching
178
+ cache_id = super().add(request=request, response=response, payload=payload) # First use standard add() to handle in-memory caching
178
179
  cache_entry = self.cache_entries[cache_id] # get the cache entry (which will exist since it was added on super().add(request, response) )
179
180
  request_domains = self.extract_domains_from_request(request) # Extract domains and areas for organization
180
181
  domains = self.shared_domains + request_domains
@@ -10,4 +10,5 @@ class Schema__LLM_Response__Cache(Type_Safe):
10
10
  hash__request : Safe_Str__Hash = None
11
11
  llm_response : Schema__LLM_Response = None
12
12
  llm_request : Schema__LLM_Request = None
13
+ llm_payload : dict
13
14
  timestamp : Timestamp_Now
@@ -1,5 +1,6 @@
1
- from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
2
- from osbot_utils.utils.Objects import base_classes_names
1
+ from typing import get_args
2
+ from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
3
+ from osbot_utils.utils.Objects import base_classes_names
3
4
 
4
5
 
5
6
  class Type_Safe__Convert:
@@ -9,6 +10,10 @@ class Type_Safe__Convert:
9
10
  obj_annotations = target.__annotations__
10
11
  if hasattr(obj_annotations,'get'):
11
12
  attribute_annotation = obj_annotations.get(attr_name)
13
+ args = get_args(attribute_annotation)
14
+ if len(args) == 2 and args[1] is type(None): # todo: find a better way to do this, since this is handling an edge case when origin_attr_type is Optional (which is an shorthand for Union[X, None] )
15
+ attribute_annotation = args[0]
16
+
12
17
  if 'Type_Safe' in base_classes_names(attribute_annotation):
13
18
  return attribute_annotation(**value)
14
19
  return value
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v2.37.0
1
+ v2.39.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osbot_utils
3
- Version: 2.37.0
3
+ Version: 2.39.0
4
4
  Summary: OWASP Security Bot - Utils
5
5
  License: MIT
6
6
  Author: Dinis Cruz
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
23
23
 
24
24
  Powerful Python util methods and classes that simplify common apis and tasks.
25
25
 
26
- ![Current Release](https://img.shields.io/badge/release-v2.37.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v2.39.0-blue)
27
27
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
28
28
 
29
29
 
@@ -190,16 +190,16 @@ osbot_utils/helpers/html/Tag__Link.py,sha256=rQ-gZN8EkSv5x1S-smdjvFflwMQHACHQXiO
190
190
  osbot_utils/helpers/html/Tag__Style.py,sha256=LPPlIN7GyMvfCUlbs2eXVMUr9jS0PX5M94A5Ig_jXIs,846
191
191
  osbot_utils/helpers/html/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
192
192
  osbot_utils/helpers/llms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
- osbot_utils/helpers/llms/actions/LLM_Request__Execute.py,sha256=JljneiEJ1ETlCBaH4cmd-bwIlIq_kFi2n2TD1bVGugU,1821
193
+ osbot_utils/helpers/llms/actions/LLM_Request__Execute.py,sha256=F921XqKGdH7M77E1OKrGcJnYBoqMKeOdXp98VVCJhKE,2025
194
194
  osbot_utils/helpers/llms/actions/Type_Safe__Schema_For__LLMs.py,sha256=em9RoSZqSSo6BQBZvEKH8Qv8f8f8oubNpy0LIDsak-E,12024
195
195
  osbot_utils/helpers/llms/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
196
- osbot_utils/helpers/llms/builders/LLM_Request__Builder.py,sha256=tfld-1hcjIH2e2qapXGAu2gq9E0k2NswPn5LRKzWfVA,3133
197
- osbot_utils/helpers/llms/builders/LLM_Request__Builder__Open_AI.py,sha256=7CUnNyGqyiD0-jX0pESQJichjx_0ttMmhO7OmqZWHl4,2918
196
+ osbot_utils/helpers/llms/builders/LLM_Request__Builder.py,sha256=c8MN66ijFn9DugbBIGmG0bm9ujS-0kvZDGqJcZsHHYc,3385
197
+ osbot_utils/helpers/llms/builders/LLM_Request__Builder__Open_AI.py,sha256=JwyPDeBUQd70Ltm801y5qvS883IIC7TcfG04D3LWdGI,3430
198
198
  osbot_utils/helpers/llms/builders/LLM_Request__Factory.py,sha256=bpFXVTKpalBL7ZONjaHU5c0-2Rwzzd2vgdD1FpYxfGw,6291
199
199
  osbot_utils/helpers/llms/builders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
200
200
  osbot_utils/helpers/llms/cache/LLM_Cache__Path_Generator.py,sha256=7kDY-aaUWR4Da6lj5RPwjqTLUTGrOUYhbNfOPM30e40,4442
201
- osbot_utils/helpers/llms/cache/LLM_Request__Cache.py,sha256=8Ayz26bteYhc4GNLpItNYlTwF4_yKvhFridDVA61fPo,6783
202
- osbot_utils/helpers/llms/cache/LLM_Request__Cache__File_System.py,sha256=m4guw6yoo8Q05PQea6SJnET5xpJMwmmXhdN-kaRvX5s,15306
201
+ osbot_utils/helpers/llms/cache/LLM_Request__Cache.py,sha256=LJM33aNi7teCUMNr6mpgl6MBfvOaa38H2KuJicBXMwg,6999
202
+ osbot_utils/helpers/llms/cache/LLM_Request__Cache__File_System.py,sha256=eIWHqUuODyG3WYoB6SmAowb-yc4Zk28SH2GjyxGDOVg,15392
203
203
  osbot_utils/helpers/llms/cache/LLM_Request__Cache__Storage.py,sha256=0ok7z2kGiK3edlgD0hwD5z2hYFZ91Viar1JgD7SNoxg,5434
204
204
  osbot_utils/helpers/llms/cache/Virtual_Storage__Local__Folder.py,sha256=xNM2xy0-2ROvhEFXa_jwqth7eApIcRTqcRUDxo0THXI,3214
205
205
  osbot_utils/helpers/llms/cache/Virtual_Storage__Sqlite.py,sha256=j8EWuKFVMtDBxrCEi8yNdpzwvTxO6Bri2Bi4-KwO-3s,4638
@@ -214,7 +214,7 @@ osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Function_Call.py,sha256=VJ
214
214
  osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Message__Content.py,sha256=nl-16yz4G_72ViACKE9CvGStrKxw2Gm_JcaU8wVcJXI,521
215
215
  osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Message__Role.py,sha256=T99w0cRrDPXQqPT-Nw7_14tMr4vKpUlhw74UJZL6w6w,168
216
216
  osbot_utils/helpers/llms/schemas/Schema__LLM_Response.py,sha256=R62zjoUqu9sbtbFcOX7vG1t0vTaAhS_3Z9CkxESrTjI,298
217
- osbot_utils/helpers/llms/schemas/Schema__LLM_Response__Cache.py,sha256=ZlD3DeKeS-29n9qiMVrsnj0M4lkZWknnP-Wn8wanu6E,786
217
+ osbot_utils/helpers/llms/schemas/Schema__LLM_Response__Cache.py,sha256=jRV637LYbj9HhRtipYsd0JBxcvRnVHcF0OFJHObGhHA,820
218
218
  osbot_utils/helpers/llms/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
219
  osbot_utils/helpers/pubsub/Event__Queue.py,sha256=bCtIdVlAuG-jvFEnz14oNhgRScEUrd8v9BqLcZleGks,5038
220
220
  osbot_utils/helpers/pubsub/PubSub__Client.py,sha256=6K3l4H-Tc0DhktrxpYzLVur1uZ532pQsHWprLNRXFJE,2316
@@ -351,7 +351,7 @@ osbot_utils/type_safe/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
351
351
  osbot_utils/type_safe/methods/type_safe_property.py,sha256=DcJkOIs6swJtkglsZVKLyFSczCGSJISOVwAmvjCOQvo,1425
352
352
  osbot_utils/type_safe/shared/Type_Safe__Annotations.py,sha256=nmVqCbhk4kUYrw_mdYqugxQlv4gM3NUUH89FYTHUg-c,1133
353
353
  osbot_utils/type_safe/shared/Type_Safe__Cache.py,sha256=G03pmpds9sTwU5z5pNLssD_GTvVSIR11nGYbkV5KaiY,7913
354
- osbot_utils/type_safe/shared/Type_Safe__Convert.py,sha256=zvaorttNKZsFUgJE9R0_x34sbY6CGppP45z2KGaVcVg,2421
354
+ osbot_utils/type_safe/shared/Type_Safe__Convert.py,sha256=q1ds7AqgNhZX1pW0SNq_VNWIudfJWHGY60oYvd3YWlo,2849
355
355
  osbot_utils/type_safe/shared/Type_Safe__Json_Compressor.py,sha256=TDbot_NNzCPXBQv0l5mksWueJNfxlVFDBGxIH8Jf_XY,5426
356
356
  osbot_utils/type_safe/shared/Type_Safe__Json_Compressor__Type_Registry.py,sha256=wYOCg7F1nTrRn8HlnZvrs_8A8WL4gxRYRLnXZpGIiuk,1119
357
357
  osbot_utils/type_safe/shared/Type_Safe__Not_Cached.py,sha256=25FAl6SOLxdStco_rm9tgOYLfuKyBWheGdl7vVa56UU,800
@@ -398,8 +398,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
398
398
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
399
399
  osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
400
400
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
401
- osbot_utils/version,sha256=-HYKMJJj0R7l-Xfl9YKo2VaYfZDmtHwPvDLtL8vC6pw,8
402
- osbot_utils-2.37.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
403
- osbot_utils-2.37.0.dist-info/METADATA,sha256=wGNRK7yAwPpR8l9L2u5kjrFc33T2tq_g4BtuF_n8UMg,1329
404
- osbot_utils-2.37.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
405
- osbot_utils-2.37.0.dist-info/RECORD,,
401
+ osbot_utils/version,sha256=qJGCI5s9nSw82EuuElCNdr2zaUbltf_E-fswKeYsGRI,8
402
+ osbot_utils-2.39.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
403
+ osbot_utils-2.39.0.dist-info/METADATA,sha256=qcgUeDsG2DpUyAbFtYabOjDWUL9lqlFQdgvBIzC4wbU,1329
404
+ osbot_utils-2.39.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
405
+ osbot_utils-2.39.0.dist-info/RECORD,,