osbot-utils 2.36.0__py3-none-any.whl → 2.38.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:
@@ -1,9 +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
8
+ from osbot_utils.helpers.safe_str.Safe_Str__Text import Safe_Str__Text
7
9
  from osbot_utils.type_safe.Type_Safe import Type_Safe
8
10
  from osbot_utils.type_safe.decorators.type_safe import type_safe
9
11
 
@@ -24,17 +26,24 @@ class LLM_Request__Builder(Type_Safe):
24
26
  def add_message__system (self, content : str = None): return self.add_message(role=Schema__LLM_Request__Message__Role.SYSTEM , content=content)
25
27
  def add_message__user (self, content : str = None): return self.add_message(role=Schema__LLM_Request__Message__Role.USER , content=content)
26
28
 
29
+ def llm_request(self) -> Schema__LLM_Request:
30
+ return Schema__LLM_Request(request_data=self.llm_request_data)
31
+
27
32
  @type_safe
28
- def set_function_call(self, parameters : Type[Type_Safe],
29
- function_name : str,
30
- description : str = ''
31
- ) -> Schema__LLM_Request__Function_Call:
33
+ def set__function_call(self, parameters : Type[Type_Safe],
34
+ function_name : str,
35
+ description : str = ''
36
+ ) -> Schema__LLM_Request__Function_Call:
32
37
  function_call = Schema__LLM_Request__Function_Call(parameters = parameters,
33
38
  function_name = function_name,
34
39
  description = description)
35
40
  self.llm_request_data.function_call = function_call
36
41
  return self
37
42
 
43
+ def set__model (self, model : Safe_Str__Text): self.llm_request_data.model = model ; return self
44
+ def set__platform (self, platform: Safe_Str__Text): self.llm_request_data.platform = platform; return self
45
+ def set__provider (self, provider: Safe_Str__Text): self.llm_request_data.provider = provider; return self
46
+ def set__model__gpt_4o_mini(self ): return self.set__model('gpt-4o-mini')
38
47
 
39
48
  @type_safe
40
49
  def build_request_payload(self) -> Dict[str, Any]:
@@ -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]:
@@ -40,9 +40,9 @@ class LLM_Request__Factory(Type_Safe): # Factory cl
40
40
  ) -> Schema__LLM_Request__Data: # Create a request that uses function calling with the specified schema.
41
41
 
42
42
  with self.request_builder as _:
43
- _.set_function_call(parameters = parameters , # Create the function call
44
- function_name = function_name,
45
- description = function_desc)
43
+ _.set__function_call(parameters = parameters, # Create the function call
44
+ function_name = function_name,
45
+ description = function_desc)
46
46
 
47
47
  _.add_message__system(content=system_prompt)
48
48
  _.add_message__user (content=user_message )
@@ -1,12 +1,13 @@
1
1
  from typing import List, Optional
2
2
  from osbot_utils.helpers.llms.schemas.Schema__LLM_Request__Function_Call import Schema__LLM_Request__Function_Call
3
3
  from osbot_utils.helpers.llms.schemas.Schema__LLM_Request__Message__Content import Schema__LLM_Request__Message__Content
4
+ from osbot_utils.helpers.safe_str.Safe_Str__Text import Safe_Str__Text
4
5
  from osbot_utils.type_safe.Type_Safe import Type_Safe
5
6
 
6
7
  class Schema__LLM_Request__Data(Type_Safe): # Schema for LLM API request data
7
- model : str # LLM model identifier
8
- platform : str
9
- provider : str
8
+ model : Safe_Str__Text # LLM model identifier
9
+ platform : Safe_Str__Text
10
+ provider : Safe_Str__Text
10
11
  messages : List [Schema__LLM_Request__Message__Content] # Message content entries
11
12
  function_call : Optional[Schema__LLM_Request__Function_Call ] = None # Details of function call
12
13
  temperature : Optional[float ] = None # Model temperature (0-1)
@@ -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,21 +10,16 @@ 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
15
20
 
16
21
  def convert_to_value_from_obj_annotation(self, target, attr_name, value): # todo: see the side effects of doing this for all ints and floats
17
22
 
18
- from osbot_utils.helpers.Guid import Guid
19
- from osbot_utils.helpers.Timestamp_Now import Timestamp_Now
20
- from osbot_utils.helpers.Random_Guid import Random_Guid
21
- from osbot_utils.helpers.Safe_Id import Safe_Id
22
- from osbot_utils.helpers.Str_ASCII import Str_ASCII
23
- from osbot_utils.helpers.Obj_Id import Obj_Id
24
-
25
- TYPE_SAFE__CONVERT_VALUE__SUPPORTED_TYPES = [Guid, Random_Guid, Safe_Id, Str_ASCII, Timestamp_Now, Obj_Id]
26
-
27
23
  if target is not None and attr_name is not None:
28
24
  if hasattr(target, '__annotations__'):
29
25
  obj_annotations = target.__annotations__
@@ -33,7 +29,7 @@ class Type_Safe__Convert:
33
29
  origin = type_safe_cache.get_origin(attribute_annotation) # Add handling for Type[T] annotations
34
30
  if origin is type and isinstance(value, str):
35
31
  return self.get_class_from_class_name(value)
36
- if attribute_annotation in TYPE_SAFE__CONVERT_VALUE__SUPPORTED_TYPES: # for now hard-coding this to just these types until we understand the side effects
32
+ if isinstance(attribute_annotation, type) and issubclass(attribute_annotation, (str, int)):
37
33
  return attribute_annotation(value)
38
34
  return value
39
35
 
@@ -1,9 +1,4 @@
1
1
  import types
2
2
  from enum import EnumMeta
3
3
 
4
- from osbot_utils.helpers.Safe_Id import Safe_Id
5
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
6
-
7
- IMMUTABLE_TYPES = (bool, int, float, complex, str, bytes, types.NoneType, EnumMeta, type,
8
- #Safe_Id, Safe_Str # ok to add since these classes use str as a base class # todo: see if we still need these
9
- )
4
+ IMMUTABLE_TYPES = (bool, int, float, complex, str, bytes, types.NoneType, EnumMeta, type)
@@ -4,13 +4,11 @@ import types
4
4
  import typing
5
5
  from enum import EnumMeta
6
6
  from typing import Any, Annotated, Optional, get_args, get_origin, ForwardRef, Type, Dict, _GenericAlias
7
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
8
7
  from osbot_utils.type_safe.shared.Type_Safe__Annotations import type_safe_annotations
9
8
  from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
10
9
  from osbot_utils.type_safe.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
11
10
  from osbot_utils.type_safe.shared.Type_Safe__Raise_Exception import type_safe_raise_exception
12
11
 
13
-
14
12
  class Type_Safe__Validation:
15
13
 
16
14
  def are_types_compatible_for_assigment(self, source_type, target_type):
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v2.36.0
1
+ v2.38.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osbot_utils
3
- Version: 2.36.0
3
+ Version: 2.38.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.36.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v2.38.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,12 +190,12 @@ 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=vR_7ManwTSyUOIF_eJK3sft1wBVadaGHkZOzspVc7T4,1987
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=FrrDTqivHXMaDifi8xDRvAbUju6a8CHnd1VleoQhp2Q,2601
197
- osbot_utils/helpers/llms/builders/LLM_Request__Builder__Open_AI.py,sha256=7CUnNyGqyiD0-jX0pESQJichjx_0ttMmhO7OmqZWHl4,2918
198
- osbot_utils/helpers/llms/builders/LLM_Request__Factory.py,sha256=M-c_odsTjTfWo45LzL8Zkr9gd0LLl2brcwMKoeZNOnc,6292
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
+ 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
201
  osbot_utils/helpers/llms/cache/LLM_Request__Cache.py,sha256=8Ayz26bteYhc4GNLpItNYlTwF4_yKvhFridDVA61fPo,6783
@@ -209,7 +209,7 @@ osbot_utils/helpers/llms/platforms/open_ai/API__LLM__Open_AI.py,sha256=Yyy2ZnIS6
209
209
  osbot_utils/helpers/llms/platforms/open_ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
210
  osbot_utils/helpers/llms/schemas/Schema__LLM_Cache__Index.py,sha256=12dUUSFhWRZvqEkNivqajqMPApPWhfSI7jWnHyBuxNw,717
211
211
  osbot_utils/helpers/llms/schemas/Schema__LLM_Request.py,sha256=7IXCf9AflRlUeFjDSqRR9CiBWlaAa1FgMzrS292e9Po,376
212
- osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Data.py,sha256=1D9zoDHbICpaxpAq4VTlYOF0-4Jys8Ohi5CrxTlEXQI,1260
212
+ osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Data.py,sha256=EpII6ZMkWACkoHYn-TNowppbIskyoaCovefPA5Q5qtA,1380
213
213
  osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Function_Call.py,sha256=VJgWi4aK-DJmuJvfY2qZUZuLkrLlmu5lgyzxZrrp3hM,440
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
@@ -351,13 +351,13 @@ 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=mS92_sKjKM_aNSB3ERMEgv-3DtkLVAS8AZF067G-JWM,2995
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
358
358
  osbot_utils/type_safe/shared/Type_Safe__Raise_Exception.py,sha256=pbru8k8CTQMNUfmFBndiJhg2KkqEYzFvJAPcNZHeHfQ,829
359
- osbot_utils/type_safe/shared/Type_Safe__Shared__Variables.py,sha256=TgF2MK__81YZaY19YWF4q1rE65BqU3HNmmN139OVcK0,409
360
- osbot_utils/type_safe/shared/Type_Safe__Validation.py,sha256=s6yRSWY6zYKEQBwlDEGFwFRO9v8T7UOaz5fsz6ih0cw,19342
359
+ osbot_utils/type_safe/shared/Type_Safe__Shared__Variables.py,sha256=SuZGl9LryQX6IpOE0I_lbzClT-h17UNylC__-M8ltTY,129
360
+ osbot_utils/type_safe/shared/Type_Safe__Validation.py,sha256=CHnrdPtVbuF9OlnFv3sfG-xwsmX5hDedXiLoI6fiiVM,19257
361
361
  osbot_utils/type_safe/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
362
362
  osbot_utils/type_safe/steps/Type_Safe__Step__Class_Kwargs.py,sha256=snoyJKvZ1crgF2fp0zexwNPnV_E63RfyRIsMAZdrKNY,6995
363
363
  osbot_utils/type_safe/steps/Type_Safe__Step__Default_Kwargs.py,sha256=tzKXDUc0HVP5QvCWsmcPuuZodNvQZ9FeMDNI2x00Ngw,1943
@@ -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=0wuMx2pp2iJlRaFRxv3KMCNynwS_XlqQIvYnQrKGDbw,8
402
- osbot_utils-2.36.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
403
- osbot_utils-2.36.0.dist-info/METADATA,sha256=yDtZSLfjqU_kaWUAJsFyHCNM9s3-EfZ7WkpQNk-Eyn0,1329
404
- osbot_utils-2.36.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
405
- osbot_utils-2.36.0.dist-info/RECORD,,
401
+ osbot_utils/version,sha256=5wV6C9vRtevBlgAl6UzZ00kufvcHsbgatM8FaiKy5Us,8
402
+ osbot_utils-2.38.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
403
+ osbot_utils-2.38.0.dist-info/METADATA,sha256=1oshM3ZIVLYEZhR_CgTKhCw7m2wWz62PvYqgCgLm22A,1329
404
+ osbot_utils-2.38.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
405
+ osbot_utils-2.38.0.dist-info/RECORD,,