unique_toolkit 0.7.9__py3-none-any.whl → 1.33.3__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.
Files changed (190) hide show
  1. unique_toolkit/__init__.py +36 -3
  2. unique_toolkit/_common/api_calling/human_verification_manager.py +357 -0
  3. unique_toolkit/_common/base_model_type_attribute.py +303 -0
  4. unique_toolkit/_common/chunk_relevancy_sorter/config.py +49 -0
  5. unique_toolkit/_common/chunk_relevancy_sorter/exception.py +5 -0
  6. unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +46 -0
  7. unique_toolkit/_common/chunk_relevancy_sorter/service.py +374 -0
  8. unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +275 -0
  9. unique_toolkit/_common/default_language_model.py +12 -0
  10. unique_toolkit/_common/docx_generator/__init__.py +7 -0
  11. unique_toolkit/_common/docx_generator/config.py +12 -0
  12. unique_toolkit/_common/docx_generator/schemas.py +80 -0
  13. unique_toolkit/_common/docx_generator/service.py +225 -0
  14. unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  15. unique_toolkit/_common/endpoint_builder.py +368 -0
  16. unique_toolkit/_common/endpoint_requestor.py +480 -0
  17. unique_toolkit/_common/exception.py +24 -0
  18. unique_toolkit/_common/experimental/endpoint_builder.py +368 -0
  19. unique_toolkit/_common/experimental/endpoint_requestor.py +488 -0
  20. unique_toolkit/_common/feature_flags/schema.py +9 -0
  21. unique_toolkit/_common/pydantic/rjsf_tags.py +936 -0
  22. unique_toolkit/_common/pydantic_helpers.py +174 -0
  23. unique_toolkit/_common/referencing.py +53 -0
  24. unique_toolkit/_common/string_utilities.py +140 -0
  25. unique_toolkit/_common/tests/test_referencing.py +521 -0
  26. unique_toolkit/_common/tests/test_string_utilities.py +506 -0
  27. unique_toolkit/_common/token/image_token_counting.py +67 -0
  28. unique_toolkit/_common/token/token_counting.py +204 -0
  29. unique_toolkit/_common/utils/__init__.py +1 -0
  30. unique_toolkit/_common/utils/files.py +43 -0
  31. unique_toolkit/_common/utils/image/encode.py +25 -0
  32. unique_toolkit/_common/utils/jinja/helpers.py +10 -0
  33. unique_toolkit/_common/utils/jinja/render.py +18 -0
  34. unique_toolkit/_common/utils/jinja/schema.py +65 -0
  35. unique_toolkit/_common/utils/jinja/utils.py +80 -0
  36. unique_toolkit/_common/utils/structured_output/__init__.py +1 -0
  37. unique_toolkit/_common/utils/structured_output/schema.py +5 -0
  38. unique_toolkit/_common/utils/write_configuration.py +51 -0
  39. unique_toolkit/_common/validators.py +101 -4
  40. unique_toolkit/agentic/__init__.py +1 -0
  41. unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +28 -0
  42. unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +278 -0
  43. unique_toolkit/agentic/evaluation/config.py +36 -0
  44. unique_toolkit/{evaluators → agentic/evaluation}/context_relevancy/prompts.py +25 -0
  45. unique_toolkit/agentic/evaluation/context_relevancy/schema.py +80 -0
  46. unique_toolkit/agentic/evaluation/context_relevancy/service.py +273 -0
  47. unique_toolkit/agentic/evaluation/evaluation_manager.py +218 -0
  48. unique_toolkit/agentic/evaluation/hallucination/constants.py +61 -0
  49. unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +112 -0
  50. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/prompts.py +1 -1
  51. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/service.py +20 -16
  52. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/utils.py +32 -21
  53. unique_toolkit/{evaluators → agentic/evaluation}/output_parser.py +20 -2
  54. unique_toolkit/{evaluators → agentic/evaluation}/schemas.py +27 -7
  55. unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +253 -0
  56. unique_toolkit/agentic/evaluation/tests/test_output_parser.py +87 -0
  57. unique_toolkit/agentic/history_manager/history_construction_with_contents.py +298 -0
  58. unique_toolkit/agentic/history_manager/history_manager.py +241 -0
  59. unique_toolkit/agentic/history_manager/loop_token_reducer.py +484 -0
  60. unique_toolkit/agentic/history_manager/utils.py +96 -0
  61. unique_toolkit/agentic/message_log_manager/__init__.py +5 -0
  62. unique_toolkit/agentic/message_log_manager/service.py +93 -0
  63. unique_toolkit/agentic/postprocessor/postprocessor_manager.py +212 -0
  64. unique_toolkit/agentic/reference_manager/reference_manager.py +103 -0
  65. unique_toolkit/agentic/responses_api/__init__.py +19 -0
  66. unique_toolkit/agentic/responses_api/postprocessors/code_display.py +71 -0
  67. unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +297 -0
  68. unique_toolkit/agentic/responses_api/stream_handler.py +15 -0
  69. unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +141 -0
  70. unique_toolkit/agentic/thinking_manager/thinking_manager.py +103 -0
  71. unique_toolkit/agentic/tools/__init__.py +1 -0
  72. unique_toolkit/agentic/tools/a2a/__init__.py +36 -0
  73. unique_toolkit/agentic/tools/a2a/config.py +17 -0
  74. unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +15 -0
  75. unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +66 -0
  76. unique_toolkit/agentic/tools/a2a/evaluation/config.py +55 -0
  77. unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +260 -0
  78. unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +9 -0
  79. unique_toolkit/agentic/tools/a2a/manager.py +55 -0
  80. unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +21 -0
  81. unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +240 -0
  82. unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +84 -0
  83. unique_toolkit/agentic/tools/a2a/postprocessing/config.py +78 -0
  84. unique_toolkit/agentic/tools/a2a/postprocessing/display.py +264 -0
  85. unique_toolkit/agentic/tools/a2a/postprocessing/references.py +101 -0
  86. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +421 -0
  87. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +2103 -0
  88. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +603 -0
  89. unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
  90. unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +6 -0
  91. unique_toolkit/agentic/tools/a2a/response_watcher/service.py +91 -0
  92. unique_toolkit/agentic/tools/a2a/tool/__init__.py +4 -0
  93. unique_toolkit/agentic/tools/a2a/tool/_memory.py +26 -0
  94. unique_toolkit/agentic/tools/a2a/tool/_schema.py +9 -0
  95. unique_toolkit/agentic/tools/a2a/tool/config.py +158 -0
  96. unique_toolkit/agentic/tools/a2a/tool/service.py +393 -0
  97. unique_toolkit/agentic/tools/agent_chunks_hanlder.py +65 -0
  98. unique_toolkit/agentic/tools/config.py +128 -0
  99. unique_toolkit/agentic/tools/factory.py +44 -0
  100. unique_toolkit/agentic/tools/mcp/__init__.py +4 -0
  101. unique_toolkit/agentic/tools/mcp/manager.py +71 -0
  102. unique_toolkit/agentic/tools/mcp/models.py +28 -0
  103. unique_toolkit/agentic/tools/mcp/tool_wrapper.py +234 -0
  104. unique_toolkit/agentic/tools/openai_builtin/__init__.py +11 -0
  105. unique_toolkit/agentic/tools/openai_builtin/base.py +46 -0
  106. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +8 -0
  107. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +88 -0
  108. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +250 -0
  109. unique_toolkit/agentic/tools/openai_builtin/manager.py +79 -0
  110. unique_toolkit/agentic/tools/schemas.py +145 -0
  111. unique_toolkit/agentic/tools/test/test_mcp_manager.py +536 -0
  112. unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +445 -0
  113. unique_toolkit/agentic/tools/tool.py +187 -0
  114. unique_toolkit/agentic/tools/tool_manager.py +492 -0
  115. unique_toolkit/agentic/tools/tool_progress_reporter.py +285 -0
  116. unique_toolkit/agentic/tools/utils/__init__.py +19 -0
  117. unique_toolkit/agentic/tools/utils/execution/__init__.py +1 -0
  118. unique_toolkit/agentic/tools/utils/execution/execution.py +286 -0
  119. unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  120. unique_toolkit/agentic/tools/utils/source_handling/schema.py +21 -0
  121. unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +207 -0
  122. unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +216 -0
  123. unique_toolkit/app/__init__.py +9 -0
  124. unique_toolkit/app/dev_util.py +180 -0
  125. unique_toolkit/app/fast_api_factory.py +131 -0
  126. unique_toolkit/app/init_sdk.py +32 -1
  127. unique_toolkit/app/schemas.py +206 -31
  128. unique_toolkit/app/unique_settings.py +367 -0
  129. unique_toolkit/app/webhook.py +77 -0
  130. unique_toolkit/chat/__init__.py +8 -1
  131. unique_toolkit/chat/deprecated/service.py +232 -0
  132. unique_toolkit/chat/functions.py +648 -78
  133. unique_toolkit/chat/rendering.py +34 -0
  134. unique_toolkit/chat/responses_api.py +461 -0
  135. unique_toolkit/chat/schemas.py +134 -2
  136. unique_toolkit/chat/service.py +115 -767
  137. unique_toolkit/content/functions.py +353 -8
  138. unique_toolkit/content/schemas.py +128 -15
  139. unique_toolkit/content/service.py +321 -45
  140. unique_toolkit/content/smart_rules.py +301 -0
  141. unique_toolkit/content/utils.py +10 -3
  142. unique_toolkit/data_extraction/README.md +96 -0
  143. unique_toolkit/data_extraction/__init__.py +11 -0
  144. unique_toolkit/data_extraction/augmented/__init__.py +5 -0
  145. unique_toolkit/data_extraction/augmented/service.py +93 -0
  146. unique_toolkit/data_extraction/base.py +25 -0
  147. unique_toolkit/data_extraction/basic/__init__.py +11 -0
  148. unique_toolkit/data_extraction/basic/config.py +18 -0
  149. unique_toolkit/data_extraction/basic/prompt.py +13 -0
  150. unique_toolkit/data_extraction/basic/service.py +55 -0
  151. unique_toolkit/embedding/service.py +103 -12
  152. unique_toolkit/framework_utilities/__init__.py +1 -0
  153. unique_toolkit/framework_utilities/langchain/__init__.py +10 -0
  154. unique_toolkit/framework_utilities/langchain/client.py +71 -0
  155. unique_toolkit/framework_utilities/langchain/history.py +19 -0
  156. unique_toolkit/framework_utilities/openai/__init__.py +6 -0
  157. unique_toolkit/framework_utilities/openai/client.py +84 -0
  158. unique_toolkit/framework_utilities/openai/message_builder.py +229 -0
  159. unique_toolkit/framework_utilities/utils.py +23 -0
  160. unique_toolkit/language_model/__init__.py +3 -0
  161. unique_toolkit/language_model/_responses_api_utils.py +93 -0
  162. unique_toolkit/language_model/builder.py +27 -11
  163. unique_toolkit/language_model/default_language_model.py +3 -0
  164. unique_toolkit/language_model/functions.py +345 -43
  165. unique_toolkit/language_model/infos.py +1288 -46
  166. unique_toolkit/language_model/reference.py +242 -0
  167. unique_toolkit/language_model/schemas.py +481 -49
  168. unique_toolkit/language_model/service.py +229 -28
  169. unique_toolkit/protocols/support.py +145 -0
  170. unique_toolkit/services/__init__.py +7 -0
  171. unique_toolkit/services/chat_service.py +1631 -0
  172. unique_toolkit/services/knowledge_base.py +1094 -0
  173. unique_toolkit/short_term_memory/service.py +178 -41
  174. unique_toolkit/smart_rules/__init__.py +0 -0
  175. unique_toolkit/smart_rules/compile.py +56 -0
  176. unique_toolkit/test_utilities/events.py +197 -0
  177. unique_toolkit-1.33.3.dist-info/METADATA +1145 -0
  178. unique_toolkit-1.33.3.dist-info/RECORD +205 -0
  179. unique_toolkit/evaluators/__init__.py +0 -1
  180. unique_toolkit/evaluators/config.py +0 -35
  181. unique_toolkit/evaluators/constants.py +0 -1
  182. unique_toolkit/evaluators/context_relevancy/constants.py +0 -32
  183. unique_toolkit/evaluators/context_relevancy/service.py +0 -53
  184. unique_toolkit/evaluators/context_relevancy/utils.py +0 -142
  185. unique_toolkit/evaluators/hallucination/constants.py +0 -41
  186. unique_toolkit-0.7.9.dist-info/METADATA +0 -413
  187. unique_toolkit-0.7.9.dist-info/RECORD +0 -64
  188. /unique_toolkit/{evaluators → agentic/evaluation}/exception.py +0 -0
  189. {unique_toolkit-0.7.9.dist-info → unique_toolkit-1.33.3.dist-info}/LICENSE +0 -0
  190. {unique_toolkit-0.7.9.dist-info → unique_toolkit-1.33.3.dist-info}/WHEEL +0 -0
@@ -0,0 +1,303 @@
1
+ """
2
+ The following can be used to define a pydantic BaseModel that has has
3
+ an attribute of type Pydantic BaseModel.
4
+
5
+ This is useful for:
6
+ - Tooldefinition for large language models (LLMs) with flexible parameters.
7
+ - General Endpoint defintions from configuration
8
+ """
9
+
10
+ import json
11
+ from enum import StrEnum
12
+ from typing import Annotated, Any, TypeVar, Union, get_args, get_origin
13
+
14
+ from jambo import SchemaConverter
15
+ from jambo.types.json_schema_type import JSONSchema
16
+ from pydantic import (
17
+ BaseModel,
18
+ BeforeValidator,
19
+ Field,
20
+ create_model,
21
+ )
22
+
23
+
24
+ def _get_actual_type(python_type: type) -> type | None | Any:
25
+ if get_origin(python_type) is not None:
26
+ origin = get_origin(python_type)
27
+ args = get_args(python_type)
28
+
29
+ if origin is Annotated:
30
+ # For Annotated types, the first argument is the actual type
31
+ if args:
32
+ actual_type = args[0]
33
+ # Recursively handle nested generic types (e.g., Annotated[Optional[str], ...])
34
+ if get_origin(actual_type) is not None:
35
+ return _get_actual_type(actual_type)
36
+ else:
37
+ raise ValueError(f"Invalid Annotated type: {python_type}")
38
+ elif origin is Union:
39
+ # For Union types (including Optional), use the first non-None type
40
+ if args:
41
+ for arg in args:
42
+ if arg is not type(None): # Skip NoneType
43
+ return _get_actual_type(arg)
44
+ raise ValueError(f"Union type contains only None: {python_type}")
45
+ else:
46
+ raise ValueError(f"Invalid Union type: {python_type}")
47
+ else:
48
+ # Other generic types, use the origin
49
+ actual_type = origin
50
+ else:
51
+ # Regular type
52
+ actual_type = python_type
53
+
54
+ return actual_type
55
+
56
+
57
+ class ParameterType(StrEnum):
58
+ STRING = "string"
59
+ INTEGER = "integer"
60
+ NUMBER = "number"
61
+ BOOLEAN = "boolean"
62
+
63
+ def to_python_type(self) -> type:
64
+ """Convert ParameterType to Python type"""
65
+
66
+ match self:
67
+ case ParameterType.STRING:
68
+ return str
69
+ case ParameterType.INTEGER:
70
+ return int
71
+ case ParameterType.NUMBER:
72
+ return float
73
+ case ParameterType.BOOLEAN:
74
+ return bool
75
+ case _:
76
+ raise ValueError(f"Invalid ParameterType: {self}")
77
+
78
+ @classmethod
79
+ def from_python_type(cls, python_type: type) -> "ParameterType":
80
+ type_to_check = _get_actual_type(python_type)
81
+
82
+ # Ensure we have a class before calling issubclass
83
+ if not isinstance(type_to_check, type):
84
+ raise ValueError(f"Invalid Python type: {python_type}")
85
+
86
+ # Check bool first since bool is a subclass of int in Python
87
+ if issubclass(type_to_check, bool):
88
+ return cls.BOOLEAN
89
+ if issubclass(type_to_check, int):
90
+ return cls.INTEGER
91
+ if issubclass(type_to_check, float):
92
+ return cls.NUMBER
93
+ if issubclass(type_to_check, str):
94
+ return cls.STRING
95
+ raise ValueError(f"Invalid Python type: {python_type}")
96
+
97
+
98
+ class Parameter(BaseModel):
99
+ type: ParameterType
100
+ name: str
101
+ description: str
102
+ required: bool
103
+
104
+
105
+ def create_pydantic_model_from_parameter_list(
106
+ title: str, parameter_list: list[Parameter]
107
+ ) -> type[BaseModel]:
108
+ """Create a Pydantic model from MCP tool's input schema"""
109
+
110
+ # Convert JSON schema properties to Pydantic fields
111
+ fields = {}
112
+ for parameter in parameter_list:
113
+ if parameter.required:
114
+ field = Field(description=parameter.description)
115
+ else:
116
+ field = Field(default=None, description=parameter.description)
117
+
118
+ fields[parameter.name] = (
119
+ parameter.type.to_python_type(),
120
+ field,
121
+ )
122
+
123
+ return create_model(title, **fields)
124
+
125
+
126
+ def convert_to_base_model_type(
127
+ value: type[BaseModel] | str | list[Parameter] | None,
128
+ ) -> type[BaseModel]:
129
+ """
130
+ BeforeValidator that ensures the final type is always of type[BaseModel].
131
+
132
+ If the input is already a BaseModel class, returns it as-is.
133
+ If the input is a list of Parameter as defined above, converts it to a BaseModel class
134
+ If the input is a str (JSON schema), converts it to a BaseModel class using SchemaConverter from Jambo.
135
+ """
136
+ if isinstance(value, type) and issubclass(value, BaseModel):
137
+ return value
138
+
139
+ if isinstance(value, list):
140
+ if all(isinstance(item, Parameter) for item in value):
141
+ return create_pydantic_model_from_parameter_list("Parameters", value)
142
+
143
+ converter = SchemaConverter()
144
+ if isinstance(value, str):
145
+ return converter.build(JSONSchema(**json.loads(value)))
146
+
147
+ raise ValueError(f"Invalid value: {value}")
148
+
149
+
150
+ def base_model_to_parameter_list(model: type[BaseModel]) -> list[Parameter]:
151
+ parameter = []
152
+ for field_name, field_info in model.model_fields.items():
153
+ parameter.append(
154
+ Parameter(
155
+ type=ParameterType.from_python_type(field_info.annotation or str),
156
+ name=field_name,
157
+ description=field_info.description or "",
158
+ required=field_info.is_required(),
159
+ )
160
+ )
161
+ return parameter
162
+
163
+
164
+ # Create the annotated type that ensures BaseModel and generates clean JSON schema
165
+
166
+ TModel = TypeVar("TModel", bound=BaseModel)
167
+
168
+
169
+ class BaseModelTypeTitle(StrEnum):
170
+ LIST_OF_PARAMETERS = "List of Parameters"
171
+ JSON_SCHEMA_AS_STRING = "JSON Schema as String"
172
+ USE_MODEL_FROM_CODE = "Use Model from Code"
173
+
174
+
175
+ ListOfParameters = Annotated[
176
+ list[Parameter], Field(title=BaseModelTypeTitle.LIST_OF_PARAMETERS.value)
177
+ ]
178
+ JSONSchemaString = Annotated[
179
+ str, Field(title=BaseModelTypeTitle.JSON_SCHEMA_AS_STRING.value)
180
+ ]
181
+ CodefinedModelType = Annotated[
182
+ None, Field(title=BaseModelTypeTitle.USE_MODEL_FROM_CODE.value)
183
+ ]
184
+
185
+
186
+ BaseModelType = Annotated[
187
+ type[TModel],
188
+ BeforeValidator(
189
+ convert_to_base_model_type,
190
+ json_schema_input_type=ListOfParameters | JSONSchemaString | CodefinedModelType,
191
+ ),
192
+ ]
193
+
194
+
195
+ def get_json_schema_extra_for_base_model_type(model: type[BaseModel]):
196
+ """
197
+ Returns a json_schema_extra mutator that injects defaults
198
+ into both the 'string' and 'list[Parameter]' branches.
199
+
200
+ This is used to define default for the "oneOf"/"anyOf" validation
201
+ of the parameters attribute.
202
+ """
203
+ sample_params = base_model_to_parameter_list(model)
204
+
205
+ def _mutate(schema: dict) -> None:
206
+ json_default = json.dumps(model.model_json_schema())
207
+ params_default = [p.model_dump() for p in sample_params]
208
+
209
+ for key in ("oneOf", "anyOf"):
210
+ if key in schema:
211
+ for entry in schema[key]:
212
+ if (
213
+ entry.get("type") == "string"
214
+ and entry.get("title")
215
+ == BaseModelTypeTitle.JSON_SCHEMA_AS_STRING.value
216
+ ):
217
+ entry["default"] = json_default
218
+ if (
219
+ entry.get("type") == "array"
220
+ and entry.get("title")
221
+ == BaseModelTypeTitle.LIST_OF_PARAMETERS.value
222
+ ):
223
+ entry["default"] = params_default
224
+
225
+ return _mutate
226
+
227
+
228
+ if __name__ == "__main__":
229
+ import json
230
+ from pathlib import Path
231
+ from typing import Generic
232
+
233
+ from openai.types.chat.chat_completion_tool_param import ChatCompletionToolParam
234
+ from openai.types.shared_params.function_definition import FunctionDefinition
235
+ from pydantic import BaseModel, Field, field_serializer
236
+
237
+ class ToolDescription(BaseModel, Generic[TModel]):
238
+ name: str = Field(
239
+ ...,
240
+ pattern=r"^[a-zA-Z1-9_-]+$",
241
+ description="Name must adhere to the pattern ^[a-zA-Z1-9_-]+$",
242
+ )
243
+ description: str = Field(
244
+ ...,
245
+ description="Description of what the tool is doing the tool",
246
+ )
247
+
248
+ strict: bool = Field(
249
+ default=False,
250
+ description="Setting strict to true will ensure function calls reliably adhere to the function schema, instead of being best effort.",
251
+ )
252
+
253
+ parameters: BaseModelType[TModel] = Field(
254
+ ...,
255
+ description="Json Schema for the tool parameters. Must be valid JSON Schema and able to convert to a Pydantic model",
256
+ )
257
+
258
+ @field_serializer("parameters")
259
+ def serialize_parameters(self, parameters: type[BaseModel]):
260
+ return parameters.model_json_schema()
261
+
262
+ def to_openai(self) -> ChatCompletionToolParam:
263
+ return ChatCompletionToolParam(
264
+ function=FunctionDefinition(
265
+ name=self.name,
266
+ description=self.description,
267
+ parameters=self.parameters.model_json_schema(),
268
+ strict=self.strict,
269
+ ),
270
+ type="function",
271
+ )
272
+
273
+ class WeatherToolParameterModel(BaseModel):
274
+ lon: float = Field(
275
+ ..., description="The longitude of the location to get the weather for"
276
+ )
277
+ lat: float = Field(
278
+ ..., description="The latitude of the location to get the weather for"
279
+ )
280
+ name: str = Field(
281
+ ..., description="The name of the location to get the weather for"
282
+ )
283
+
284
+ class GetWeatherTool(ToolDescription[WeatherToolParameterModel]):
285
+ parameters: BaseModelType[WeatherToolParameterModel] = Field(
286
+ default=WeatherToolParameterModel,
287
+ json_schema_extra=get_json_schema_extra_for_base_model_type(
288
+ WeatherToolParameterModel
289
+ ),
290
+ )
291
+
292
+ # The json schema can be used in the RSJF library to create a valid frontend component.
293
+ # You can test it on https://rjsf-team.github.io/react-jsonschema-form/
294
+ file = Path(__file__).parent / "weather_tool_schema.json"
295
+ with file.open("w") as f:
296
+ f.write(json.dumps(GetWeatherTool.model_json_schema(), indent=2))
297
+
298
+ # Notice that the t.parameters is a pydantic model with type annotations
299
+ t = GetWeatherTool(
300
+ name="GetWeather", description="Get the weather for a given location"
301
+ )
302
+ t.parameters(lon=100, lat=100, name="Test")
303
+ print(t.model_dump())
@@ -0,0 +1,49 @@
1
+ from typing import Annotated, Any
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from unique_toolkit._common.validators import LMI, get_LMI_default_field
6
+ from unique_toolkit.agentic.evaluation.context_relevancy.schema import (
7
+ StructuredOutputConfig,
8
+ )
9
+ from unique_toolkit.agentic.tools.config import get_configuration_dict
10
+ from unique_toolkit.language_model.default_language_model import DEFAULT_GPT_4o
11
+
12
+
13
+ class ChunkRelevancySortConfig(BaseModel):
14
+ model_config = get_configuration_dict()
15
+ enabled: bool = Field(
16
+ default=False,
17
+ description="Whether to enable the chunk relevancy sort.",
18
+ )
19
+ relevancy_levels_to_consider: list[str] = Field(
20
+ default=["high", "medium", "low"],
21
+ description="The relevancy levels to consider.",
22
+ )
23
+ relevancy_level_order: dict[str, int] = Field(
24
+ default={"high": 0, "medium": 1, "low": 2},
25
+ description="The relevancy level order.",
26
+ )
27
+ language_model: LMI = get_LMI_default_field(
28
+ DEFAULT_GPT_4o,
29
+ description="The language model to use for the chunk relevancy sort.",
30
+ )
31
+ fallback_language_model: LMI = get_LMI_default_field(
32
+ DEFAULT_GPT_4o,
33
+ description="The language model to use as a fallback.",
34
+ )
35
+ additional_llm_options: dict[str, Any] = Field(
36
+ default={},
37
+ description="Additional options to pass to the language model.",
38
+ )
39
+ structured_output_config: StructuredOutputConfig = Field(
40
+ default_factory=StructuredOutputConfig,
41
+ description="The configuration for the structured output.",
42
+ )
43
+ max_tasks: (
44
+ Annotated[int, Field(title="Limited")]
45
+ | Annotated[None, Field(title="Unlimited")]
46
+ ) = Field(
47
+ default=1000,
48
+ description="The maximum number of tasks to run in parallel.",
49
+ )
@@ -0,0 +1,5 @@
1
+ from unique_toolkit._common.exception import CommonException
2
+
3
+
4
+ class ChunkRelevancySorterException(CommonException):
5
+ pass
@@ -0,0 +1,46 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from unique_toolkit.agentic.evaluation.schemas import EvaluationMetricResult
6
+ from unique_toolkit.content.schemas import ContentChunk
7
+
8
+
9
+ class ChunkRelevancy(BaseModel):
10
+ chunk: ContentChunk
11
+ relevancy: EvaluationMetricResult | None = None
12
+
13
+ def get_document_name(self):
14
+ title = self.chunk.key or self.chunk.title or "Unkown"
15
+ return title.split(":")[0]
16
+
17
+ def get_page_number(self):
18
+ start_page = self.chunk.start_page
19
+ end_page = self.chunk.end_page
20
+
21
+ if start_page is None or end_page is None:
22
+ return start_page or end_page or "Unknown Page"
23
+ elif start_page == end_page:
24
+ return str(start_page)
25
+ else:
26
+ return f"{start_page}-{end_page}"
27
+
28
+ def get_facts(self):
29
+ if self.relevancy is None:
30
+ return []
31
+ return self.relevancy.fact_list
32
+
33
+
34
+ class ChunkRelevancySorterResult(BaseModel):
35
+ relevancies: list[ChunkRelevancy]
36
+ user_message: Optional[str] = None
37
+
38
+ @staticmethod
39
+ def from_chunks(chunks: list[ContentChunk]):
40
+ return ChunkRelevancySorterResult(
41
+ relevancies=[ChunkRelevancy(chunk=chunk) for chunk in chunks],
42
+ )
43
+
44
+ @property
45
+ def content_chunks(self):
46
+ return [chunk.chunk for chunk in self.relevancies]