unique_toolkit 0.7.24__py3-none-any.whl → 0.7.26__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.
- unique_toolkit/app/schemas.py +26 -8
- unique_toolkit/content/functions.py +7 -6
- unique_toolkit/content/schemas.py +2 -2
- unique_toolkit/content/service.py +3 -2
- unique_toolkit/language_model/infos.py +38 -0
- unique_toolkit/smart_rules/__init__.py +0 -0
- unique_toolkit/smart_rules/compile.py +301 -0
- {unique_toolkit-0.7.24.dist-info → unique_toolkit-0.7.26.dist-info}/METADATA +9 -1
- {unique_toolkit-0.7.24.dist-info → unique_toolkit-0.7.26.dist-info}/RECORD +11 -9
- {unique_toolkit-0.7.24.dist-info → unique_toolkit-0.7.26.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.7.24.dist-info → unique_toolkit-0.7.26.dist-info}/WHEEL +0 -0
unique_toolkit/app/schemas.py
CHANGED
@@ -2,9 +2,11 @@ from enum import StrEnum
|
|
2
2
|
from typing import Any, Optional
|
3
3
|
|
4
4
|
from humps import camelize
|
5
|
-
from pydantic import BaseModel, ConfigDict, Field
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
6
6
|
from typing_extensions import deprecated
|
7
7
|
|
8
|
+
from unique_toolkit.smart_rules.compile import UniqueQL, parse_uniqueql
|
9
|
+
|
8
10
|
# set config to convert camelCase to snake_case
|
9
11
|
model_config = ConfigDict(
|
10
12
|
alias_generator=camelize,
|
@@ -95,15 +97,31 @@ class ChatEventPayload(BaseModel):
|
|
95
97
|
assistant_id: str
|
96
98
|
user_message: ChatEventUserMessage
|
97
99
|
assistant_message: ChatEventAssistantMessage
|
98
|
-
text:
|
99
|
-
additional_parameters:
|
100
|
-
user_metadata:
|
101
|
-
|
102
|
-
|
100
|
+
text: str | None = None
|
101
|
+
additional_parameters: ChatEventAdditionalParameters | None = None
|
102
|
+
user_metadata: dict[str, Any] | None = Field(
|
103
|
+
default_factory=dict,
|
104
|
+
)
|
105
|
+
tool_choices: list[str] = Field(
|
106
|
+
default_factory=list,
|
103
107
|
description="A list containing the tool names the user has chosen to be activated.",
|
104
108
|
)
|
105
|
-
tool_parameters:
|
106
|
-
|
109
|
+
tool_parameters: dict[str, Any] = Field(
|
110
|
+
default_factory=dict,
|
111
|
+
description="Parameters extracted from module selection function calling the tool.",
|
112
|
+
)
|
113
|
+
metadata_filter: dict[str, Any] = Field(
|
114
|
+
default_factory=dict,
|
115
|
+
description="Metadata filter compiled after module selection function calling and scope rules.",
|
116
|
+
)
|
117
|
+
raw_scope_rules: UniqueQL | None = Field(
|
118
|
+
default=None,
|
119
|
+
description="Raw UniqueQL rule that can be compiled to a metadata filter.",
|
120
|
+
)
|
121
|
+
|
122
|
+
@field_validator("raw_scope_rules", mode="before")
|
123
|
+
def validate_scope_rules(cls, value: dict[str, Any]) -> UniqueQL:
|
124
|
+
return parse_uniqueql(value)
|
107
125
|
|
108
126
|
|
109
127
|
@deprecated("""Use `ChatEventPayload` instead.
|
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
import re
|
4
4
|
import tempfile
|
5
5
|
from pathlib import Path
|
6
|
+
from typing import Any
|
6
7
|
|
7
8
|
import requests
|
8
9
|
import unique_sdk
|
@@ -214,7 +215,7 @@ def upload_content_from_bytes(
|
|
214
215
|
chat_id: str | None = None,
|
215
216
|
skip_ingestion: bool = False,
|
216
217
|
ingestion_config: unique_sdk.Content.IngestionConfig | None = None,
|
217
|
-
metadata: dict[str,
|
218
|
+
metadata: dict[str, Any] | None = None,
|
218
219
|
):
|
219
220
|
"""
|
220
221
|
Uploads content to the knowledge base.
|
@@ -229,7 +230,7 @@ def upload_content_from_bytes(
|
|
229
230
|
chat_id (str | None): The chat ID. Defaults to None.
|
230
231
|
skip_ingestion (bool): Whether to skip ingestion. Defaults to False.
|
231
232
|
ingestion_config (unique_sdk.Content.IngestionConfig | None): The ingestion configuration. Defaults to None.
|
232
|
-
metadata ( dict[str,
|
233
|
+
metadata ( dict[str, Any] | None): The metadata for the content. Defaults to None.
|
233
234
|
|
234
235
|
Returns:
|
235
236
|
Content: The uploaded content.
|
@@ -263,7 +264,7 @@ def upload_content(
|
|
263
264
|
chat_id: str | None = None,
|
264
265
|
skip_ingestion: bool = False,
|
265
266
|
ingestion_config: unique_sdk.Content.IngestionConfig | None = None,
|
266
|
-
metadata: dict[str,
|
267
|
+
metadata: dict[str, Any] | None = None,
|
267
268
|
):
|
268
269
|
"""
|
269
270
|
Uploads content to the knowledge base.
|
@@ -278,7 +279,7 @@ def upload_content(
|
|
278
279
|
chat_id (str | None): The chat ID. Defaults to None.
|
279
280
|
skip_ingestion (bool): Whether to skip ingestion. Defaults to False.
|
280
281
|
ingestion_config (unique_sdk.Content.IngestionConfig | None): The ingestion configuration. Defaults to None.
|
281
|
-
metadata ( dict[str,
|
282
|
+
metadata ( dict[str, Any] | None): The metadata for the content. Defaults to None.
|
282
283
|
|
283
284
|
Returns:
|
284
285
|
Content: The uploaded content.
|
@@ -312,7 +313,7 @@ def _trigger_upload_content(
|
|
312
313
|
chat_id: str | None = None,
|
313
314
|
skip_ingestion: bool = False,
|
314
315
|
ingestion_config: unique_sdk.Content.IngestionConfig | None = None,
|
315
|
-
metadata: dict[str,
|
316
|
+
metadata: dict[str, Any] | None = None,
|
316
317
|
):
|
317
318
|
"""
|
318
319
|
Uploads content to the knowledge base.
|
@@ -327,7 +328,7 @@ def _trigger_upload_content(
|
|
327
328
|
chat_id (str | None): The chat ID. Defaults to None.
|
328
329
|
skip_ingestion (bool): Whether to skip ingestion. Defaults to False.
|
329
330
|
ingestion_config (unique_sdk.Content.IngestionConfig | None): The ingestion configuration. Defaults to None.
|
330
|
-
metadata (dict[str,
|
331
|
+
metadata (dict[str, Any] | None): The metadata for the content. Defaults to None.
|
331
332
|
|
332
333
|
Returns:
|
333
334
|
Content: The uploaded content.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from enum import StrEnum
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Any, Optional
|
4
4
|
|
5
5
|
from humps import camelize
|
6
6
|
from pydantic import BaseModel, ConfigDict, Field
|
@@ -54,7 +54,7 @@ class Content(BaseModel):
|
|
54
54
|
read_url: str | None = None
|
55
55
|
created_at: datetime | None = None
|
56
56
|
updated_at: datetime | None = None
|
57
|
-
metadata: dict[str,
|
57
|
+
metadata: dict[str, Any] | None = None
|
58
58
|
ingestion_config: dict | None = None
|
59
59
|
|
60
60
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
from pathlib import Path
|
3
|
+
from typing import Any
|
3
4
|
|
4
5
|
import unique_sdk
|
5
6
|
from requests import Response
|
@@ -408,7 +409,7 @@ class ContentService:
|
|
408
409
|
chat_id: str | None = None,
|
409
410
|
skip_ingestion: bool = False,
|
410
411
|
ingestion_config: unique_sdk.Content.IngestionConfig | None = None,
|
411
|
-
metadata: dict[str,
|
412
|
+
metadata: dict[str, Any] | None = None,
|
412
413
|
):
|
413
414
|
"""
|
414
415
|
Uploads content to the knowledge base.
|
@@ -421,7 +422,7 @@ class ContentService:
|
|
421
422
|
chat_id (str | None): The chat ID. Defaults to None.
|
422
423
|
skip_ingestion (bool): Whether to skip ingestion. Defaults to False.
|
423
424
|
ingestion_config (unique_sdk.Content.IngestionConfig | None): The ingestion configuration. Defaults to None.
|
424
|
-
metadata (dict[str,
|
425
|
+
metadata (dict[str, Any] | None): The metadata to associate with the content. Defaults to None.
|
425
426
|
|
426
427
|
Returns:
|
427
428
|
Content: The uploaded content.
|
@@ -23,6 +23,8 @@ class LanguageModelName(StrEnum):
|
|
23
23
|
AZURE_o3_MINI_2025_0131 = "AZURE_o3_MINI_2025_0131"
|
24
24
|
AZURE_GPT_45_PREVIEW_2025_0227 = "AZURE_GPT_45_PREVIEW_2025_0227"
|
25
25
|
AZURE_GPT_41_2025_0414 = "AZURE_GPT_41_2025_0414"
|
26
|
+
AZURE_GPT_41_MINI_2025_0414 = "AZURE_GPT_41_MINI_2025_0414"
|
27
|
+
AZURE_GPT_41_NANO_2025_0414 = "AZURE_GPT_41_NANO_2025_0414"
|
26
28
|
AZURE_o3_2025_0416 = "AZURE_o3_2025_0416"
|
27
29
|
AZURE_o4_MINI_2025_0416 = "AZURE_o4_MINI_2025_0416"
|
28
30
|
ANTHROPIC_CLAUDE_3_7_SONNET = "litellm:anthropic-claude-3-7-sonnet"
|
@@ -378,6 +380,42 @@ class LanguageModelInfo(BaseModel):
|
|
378
380
|
info_cutoff_at=date(2024, 5, 31),
|
379
381
|
published_at=date(2025, 4, 14),
|
380
382
|
)
|
383
|
+
case LanguageModelName.AZURE_GPT_41_MINI_2025_0414:
|
384
|
+
return cls(
|
385
|
+
name=model_name,
|
386
|
+
capabilities=[
|
387
|
+
ModelCapabilities.STRUCTURED_OUTPUT,
|
388
|
+
ModelCapabilities.FUNCTION_CALLING,
|
389
|
+
ModelCapabilities.STREAMING,
|
390
|
+
ModelCapabilities.VISION,
|
391
|
+
],
|
392
|
+
provider=LanguageModelProvider.AZURE,
|
393
|
+
version="2025-04-14",
|
394
|
+
encoder_name=EncoderName.O200K_BASE,
|
395
|
+
token_limits=LanguageModelTokenLimits(
|
396
|
+
token_limit_input=1_047_576, token_limit_output=32_768
|
397
|
+
),
|
398
|
+
info_cutoff_at=date(2024, 5, 31),
|
399
|
+
published_at=date(2025, 4, 14),
|
400
|
+
)
|
401
|
+
case LanguageModelName.AZURE_GPT_41_NANO_2025_0414:
|
402
|
+
return cls(
|
403
|
+
name=model_name,
|
404
|
+
capabilities=[
|
405
|
+
ModelCapabilities.STRUCTURED_OUTPUT,
|
406
|
+
ModelCapabilities.FUNCTION_CALLING,
|
407
|
+
ModelCapabilities.STREAMING,
|
408
|
+
ModelCapabilities.VISION,
|
409
|
+
],
|
410
|
+
provider=LanguageModelProvider.AZURE,
|
411
|
+
version="2025-04-14",
|
412
|
+
encoder_name=EncoderName.O200K_BASE,
|
413
|
+
token_limits=LanguageModelTokenLimits(
|
414
|
+
token_limit_input=1_047_576, token_limit_output=32_768
|
415
|
+
),
|
416
|
+
info_cutoff_at=date(2024, 5, 31),
|
417
|
+
published_at=date(2025, 4, 14),
|
418
|
+
)
|
381
419
|
case LanguageModelName.ANTHROPIC_CLAUDE_3_7_SONNET:
|
382
420
|
return cls(
|
383
421
|
name=model_name,
|
File without changes
|
@@ -0,0 +1,301 @@
|
|
1
|
+
import re
|
2
|
+
from datetime import datetime, timedelta, timezone
|
3
|
+
from enum import Enum
|
4
|
+
from typing import Any, Dict, List, Self, Union
|
5
|
+
|
6
|
+
from pydantic import AliasChoices, BaseModel, Field
|
7
|
+
from pydantic.config import ConfigDict
|
8
|
+
|
9
|
+
|
10
|
+
class Operator(str, Enum):
|
11
|
+
EQUALS = "equals"
|
12
|
+
NOT_EQUALS = "notEquals"
|
13
|
+
GREATER_THAN = "greaterThan"
|
14
|
+
GREATER_THAN_OR_EQUAL = "greaterThanOrEqual"
|
15
|
+
LESS_THAN = "lessThan"
|
16
|
+
LESS_THAN_OR_EQUAL = "lessThanOrEqual"
|
17
|
+
IN = "in"
|
18
|
+
NOT_IN = "notIn"
|
19
|
+
CONTAINS = "contains"
|
20
|
+
NOT_CONTAINS = "notContains"
|
21
|
+
IS_NULL = "isNull"
|
22
|
+
IS_NOT_NULL = "isNotNull"
|
23
|
+
IS_EMPTY = "isEmpty"
|
24
|
+
IS_NOT_EMPTY = "isNotEmpty"
|
25
|
+
NESTED = "nested"
|
26
|
+
|
27
|
+
|
28
|
+
class BaseStatement(BaseModel):
|
29
|
+
model_config: ConfigDict = {"serialize_by_alias": True}
|
30
|
+
|
31
|
+
def with_variables(
|
32
|
+
self,
|
33
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
34
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
35
|
+
) -> Self:
|
36
|
+
return self._fill_in_variables(user_metadata, tool_parameters)
|
37
|
+
|
38
|
+
def is_compiled(self) -> bool:
|
39
|
+
# Serialize the object to json string
|
40
|
+
json_str = self.model_dump_json()
|
41
|
+
# Check if the json string has <T> or <T+> or <T-> or <toolParameters or <userMetadata
|
42
|
+
return (
|
43
|
+
"<T>" in json_str
|
44
|
+
or "<T+" in json_str
|
45
|
+
or "<T-" in json_str
|
46
|
+
or "<toolParameters" in json_str
|
47
|
+
or "<userMetadata" in json_str
|
48
|
+
)
|
49
|
+
|
50
|
+
def _fill_in_variables(
|
51
|
+
self,
|
52
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
53
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
54
|
+
) -> Self:
|
55
|
+
return self.model_copy()
|
56
|
+
|
57
|
+
|
58
|
+
class Statement(BaseStatement):
|
59
|
+
operator: Operator
|
60
|
+
value: Union[str, int, bool, list[str], "AndStatement", "OrStatement"]
|
61
|
+
path: List[str] = Field(default_factory=list)
|
62
|
+
|
63
|
+
def _fill_in_variables(
|
64
|
+
self,
|
65
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
66
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
67
|
+
) -> Self:
|
68
|
+
new_stmt = self.model_copy()
|
69
|
+
new_stmt.value = eval_operator(self, user_metadata, tool_parameters)
|
70
|
+
return new_stmt
|
71
|
+
|
72
|
+
|
73
|
+
class AndStatement(BaseStatement):
|
74
|
+
and_list: List[Union["Statement", "AndStatement", "OrStatement"]] = Field(
|
75
|
+
alias="and", validation_alias=AliasChoices("and", "and_list")
|
76
|
+
)
|
77
|
+
|
78
|
+
def _fill_in_variables(
|
79
|
+
self,
|
80
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
81
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
82
|
+
) -> Self:
|
83
|
+
new_stmt = self.model_copy()
|
84
|
+
new_stmt.and_list = [
|
85
|
+
sub_query._fill_in_variables(user_metadata, tool_parameters)
|
86
|
+
for sub_query in self.and_list
|
87
|
+
]
|
88
|
+
return new_stmt
|
89
|
+
|
90
|
+
|
91
|
+
class OrStatement(BaseStatement):
|
92
|
+
or_list: List[Union["Statement", "AndStatement", "OrStatement"]] = Field(
|
93
|
+
alias="or", validation_alias=AliasChoices("or", "or_list")
|
94
|
+
)
|
95
|
+
|
96
|
+
def _fill_in_variables(
|
97
|
+
self,
|
98
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
99
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
100
|
+
) -> Self:
|
101
|
+
new_stmt = self.model_copy()
|
102
|
+
new_stmt.or_list = [
|
103
|
+
sub_query._fill_in_variables(user_metadata, tool_parameters)
|
104
|
+
for sub_query in self.or_list
|
105
|
+
]
|
106
|
+
return new_stmt
|
107
|
+
|
108
|
+
|
109
|
+
# Update the forward references
|
110
|
+
Statement.model_rebuild()
|
111
|
+
AndStatement.model_rebuild()
|
112
|
+
OrStatement.model_rebuild()
|
113
|
+
|
114
|
+
|
115
|
+
UniqueQL = Union[Statement, AndStatement, OrStatement]
|
116
|
+
|
117
|
+
|
118
|
+
def is_array_of_strings(value: Any) -> bool:
|
119
|
+
return isinstance(value, list) and all(isinstance(item, str) for item in value)
|
120
|
+
|
121
|
+
|
122
|
+
def eval_operator(
|
123
|
+
query: Statement,
|
124
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
125
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
126
|
+
) -> Any:
|
127
|
+
if query.operator in [
|
128
|
+
Operator.EQUALS,
|
129
|
+
Operator.NOT_EQUALS,
|
130
|
+
Operator.GREATER_THAN,
|
131
|
+
Operator.GREATER_THAN_OR_EQUAL,
|
132
|
+
Operator.LESS_THAN,
|
133
|
+
Operator.LESS_THAN_OR_EQUAL,
|
134
|
+
Operator.CONTAINS,
|
135
|
+
Operator.NOT_CONTAINS,
|
136
|
+
]:
|
137
|
+
return binary_operator(query.value, user_metadata, tool_parameters)
|
138
|
+
elif query.operator in [Operator.IS_NULL, Operator.IS_NOT_NULL]:
|
139
|
+
return null_operator(query.value, user_metadata, tool_parameters)
|
140
|
+
elif query.operator in [Operator.IS_EMPTY, Operator.IS_NOT_EMPTY]:
|
141
|
+
return empty_operator(query.operator, user_metadata, tool_parameters)
|
142
|
+
elif query.operator == Operator.NESTED:
|
143
|
+
return eval_nested_operator(query.value, user_metadata, tool_parameters)
|
144
|
+
elif query.operator in [Operator.IN, Operator.NOT_IN]:
|
145
|
+
return array_operator(query.value, user_metadata, tool_parameters)
|
146
|
+
else:
|
147
|
+
raise ValueError(f"Operator {query.operator} not supported")
|
148
|
+
|
149
|
+
|
150
|
+
def eval_nested_operator(
|
151
|
+
value: Any,
|
152
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
153
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
154
|
+
) -> Union[AndStatement, OrStatement]:
|
155
|
+
if not isinstance(value, (AndStatement, OrStatement)):
|
156
|
+
raise ValueError("Nested operator must be an AndStatement or OrStatement")
|
157
|
+
return value._fill_in_variables(user_metadata, tool_parameters)
|
158
|
+
|
159
|
+
|
160
|
+
def binary_operator(
|
161
|
+
value: Any,
|
162
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
163
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
164
|
+
) -> Any:
|
165
|
+
return replace_variables(value, user_metadata, tool_parameters)
|
166
|
+
|
167
|
+
|
168
|
+
def array_operator(
|
169
|
+
value: Any,
|
170
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
171
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
172
|
+
) -> Any:
|
173
|
+
if is_array_of_strings(value):
|
174
|
+
return [
|
175
|
+
replace_variables(item, user_metadata, tool_parameters) for item in value
|
176
|
+
]
|
177
|
+
return value
|
178
|
+
|
179
|
+
|
180
|
+
def null_operator(
|
181
|
+
value: Any,
|
182
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
183
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
184
|
+
) -> Any:
|
185
|
+
return value # do nothing for now. No variables to replace
|
186
|
+
|
187
|
+
|
188
|
+
def empty_operator(
|
189
|
+
operator: Operator,
|
190
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
191
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
192
|
+
) -> Any:
|
193
|
+
"""Handle IS_EMPTY and IS_NOT_EMPTY operators."""
|
194
|
+
if operator == Operator.IS_EMPTY:
|
195
|
+
return ""
|
196
|
+
elif operator == Operator.IS_NOT_EMPTY:
|
197
|
+
return "not_empty"
|
198
|
+
return None
|
199
|
+
|
200
|
+
|
201
|
+
def calculate_current_date() -> str:
|
202
|
+
"""Calculate current date in UTC with seconds precision."""
|
203
|
+
return datetime.now(timezone.utc).isoformat(timespec="seconds")
|
204
|
+
|
205
|
+
|
206
|
+
def calculate_earlier_date(input_str: str) -> str:
|
207
|
+
match = re.search(r"<T-(\d+)>", input_str)
|
208
|
+
if not match:
|
209
|
+
return calculate_current_date() # Return current date if no match
|
210
|
+
days = int(match.group(1))
|
211
|
+
return (datetime.now(timezone.utc) - timedelta(days=days)).isoformat(
|
212
|
+
timespec="seconds"
|
213
|
+
)
|
214
|
+
|
215
|
+
|
216
|
+
def calculate_later_date(input_str: str) -> str:
|
217
|
+
match = re.search(r"<T\+(\d+)>", input_str) # Note: escaped + in regex
|
218
|
+
if not match:
|
219
|
+
return calculate_current_date() # Return current date if no match
|
220
|
+
days = int(match.group(1))
|
221
|
+
return (datetime.now(timezone.utc) + timedelta(days=days)).isoformat(
|
222
|
+
timespec="seconds"
|
223
|
+
)
|
224
|
+
|
225
|
+
|
226
|
+
def replace_variables(
|
227
|
+
value: Any,
|
228
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
229
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
230
|
+
) -> Any:
|
231
|
+
if isinstance(value, str):
|
232
|
+
if "||" in value:
|
233
|
+
return get_fallback_values(value, user_metadata, tool_parameters)
|
234
|
+
elif value == "<T>":
|
235
|
+
return calculate_current_date()
|
236
|
+
elif "<T-" in value:
|
237
|
+
return calculate_earlier_date(value)
|
238
|
+
elif "<T+" in value:
|
239
|
+
return calculate_later_date(value)
|
240
|
+
|
241
|
+
value = replace_tool_parameters_patterns(value, tool_parameters)
|
242
|
+
value = replace_user_metadata_patterns(value, user_metadata)
|
243
|
+
|
244
|
+
if value == "":
|
245
|
+
return value
|
246
|
+
try:
|
247
|
+
return int(value)
|
248
|
+
except ValueError:
|
249
|
+
if value.lower() in ["true", "false"]:
|
250
|
+
return value.lower() == "true"
|
251
|
+
return value
|
252
|
+
return value
|
253
|
+
|
254
|
+
|
255
|
+
def replace_tool_parameters_patterns(
|
256
|
+
value: str, tool_parameters: Dict[str, Union[str, int, bool]]
|
257
|
+
) -> str:
|
258
|
+
def replace_match(match):
|
259
|
+
param_name = match.group(1)
|
260
|
+
return str(tool_parameters.get(param_name, ""))
|
261
|
+
|
262
|
+
return re.sub(r"<toolParameters\.(\w+)>", replace_match, value)
|
263
|
+
|
264
|
+
|
265
|
+
def replace_user_metadata_patterns(
|
266
|
+
value: str, user_metadata: Dict[str, Union[str, int, bool]]
|
267
|
+
) -> str:
|
268
|
+
def replace_match(match):
|
269
|
+
param_name = match.group(1)
|
270
|
+
return str(user_metadata.get(param_name, ""))
|
271
|
+
|
272
|
+
return re.sub(r"<userMetadata\.(\w+)>", replace_match, value)
|
273
|
+
|
274
|
+
|
275
|
+
def get_fallback_values(
|
276
|
+
value: str,
|
277
|
+
user_metadata: Dict[str, Union[str, int, bool]],
|
278
|
+
tool_parameters: Dict[str, Union[str, int, bool]],
|
279
|
+
) -> Any:
|
280
|
+
values = value.split("||")
|
281
|
+
for val in values:
|
282
|
+
data = replace_variables(val, user_metadata, tool_parameters)
|
283
|
+
if data != "":
|
284
|
+
return data
|
285
|
+
return values
|
286
|
+
|
287
|
+
|
288
|
+
# Example usage:
|
289
|
+
def parse_uniqueql(json_data: Dict[str, Any]) -> UniqueQL:
|
290
|
+
if "operator" in json_data:
|
291
|
+
return Statement.model_validate(json_data)
|
292
|
+
elif "or" in json_data:
|
293
|
+
return OrStatement.model_validate(
|
294
|
+
{"or": [parse_uniqueql(item) for item in json_data["or"]]}
|
295
|
+
)
|
296
|
+
elif "and" in json_data:
|
297
|
+
return AndStatement.model_validate(
|
298
|
+
{"and": [parse_uniqueql(item) for item in json_data["and"]]}
|
299
|
+
)
|
300
|
+
else:
|
301
|
+
raise ValueError("Invalid UniqueQL format")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: unique_toolkit
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.26
|
4
4
|
Summary:
|
5
5
|
License: Proprietary
|
6
6
|
Author: Martin Fadler
|
@@ -111,6 +111,14 @@ All notable changes to this project will be documented in this file.
|
|
111
111
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
112
112
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
113
113
|
|
114
|
+
|
115
|
+
## [0.7.26] - 2025-06-05
|
116
|
+
- Add `scope_rules` to `ChatEventPayload`
|
117
|
+
- Added `UniqueQL` compiler and pydantic classes for `UniqueQL`. Note this is functionally equivalent but not identical to `UQLOperator` or `UQLCombinator` in `unique_sdk`.
|
118
|
+
|
119
|
+
## [0.7.25] - 2025-06-05
|
120
|
+
- Adding models `AZURE_GPT_41_MINI_2025_0414`, `AZURE_GPT_41_NANO_2025_0414`
|
121
|
+
|
114
122
|
## [0.7.24] - 2025-05-30
|
115
123
|
- Adding litellm model `gemini-2-5-flash-preview-05-20`, `anthropic-claude-sonnet-4` and `anthropic-claude-opus-4`
|
116
124
|
|
@@ -9,7 +9,7 @@ unique_toolkit/app/init_logging.py,sha256=Sh26SRxOj8i8dzobKhYha2lLrkrMTHfB1V4jR3
|
|
9
9
|
unique_toolkit/app/init_sdk.py,sha256=Nv4Now4pMfM0AgRhbtatLpm_39rKxn0WmRLwmPhRl-8,1285
|
10
10
|
unique_toolkit/app/performance/async_tasks.py,sha256=H0l3OAcosLwNHZ8d2pd-Di4wHIXfclEvagi5kfqLFPA,1941
|
11
11
|
unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
|
12
|
-
unique_toolkit/app/schemas.py,sha256=
|
12
|
+
unique_toolkit/app/schemas.py,sha256=c2Tu3woqc7gGuHYEspL0mOEyvmqOxTcavbnzZJhSYAs,3969
|
13
13
|
unique_toolkit/app/verification.py,sha256=GxFFwcJMy25fCA_Xe89wKW7bgqOu8PAs5y8QpHF0GSc,3861
|
14
14
|
unique_toolkit/chat/__init__.py,sha256=LRs2G-JTVuci4lbtHTkVUiNcZcSR6uqqfnAyo7af6nY,619
|
15
15
|
unique_toolkit/chat/constants.py,sha256=05kq6zjqUVB2d6_P7s-90nbljpB3ryxwCI-CAz0r2O4,83
|
@@ -20,9 +20,9 @@ unique_toolkit/chat/state.py,sha256=Cjgwv_2vhDFbV69xxsn7SefhaoIAEqLx3ferdVFCnOg,
|
|
20
20
|
unique_toolkit/chat/utils.py,sha256=ihm-wQykBWhB4liR3LnwPVPt_qGW6ETq21Mw4HY0THE,854
|
21
21
|
unique_toolkit/content/__init__.py,sha256=EdJg_A_7loEtCQf4cah3QARQreJx6pdz89Rm96YbMVg,940
|
22
22
|
unique_toolkit/content/constants.py,sha256=1iy4Y67xobl5VTnJB6SxSyuoBWbdLl9244xfVMUZi5o,60
|
23
|
-
unique_toolkit/content/functions.py,sha256=
|
24
|
-
unique_toolkit/content/schemas.py,sha256=
|
25
|
-
unique_toolkit/content/service.py,sha256=
|
23
|
+
unique_toolkit/content/functions.py,sha256=0ELepm3_sl0SD_SYzvQVQ-jTdrcUqK5mVJZv0nQBuAw,18367
|
24
|
+
unique_toolkit/content/schemas.py,sha256=iednldGojmoy9iPZwuIW23BfhWLE9G-fG_qAhxSgr7k,2451
|
25
|
+
unique_toolkit/content/service.py,sha256=i7Cf6eQUwBjJntzBfQUvO8JiIjGsNLnsSl9FAwij8xw,19461
|
26
26
|
unique_toolkit/content/utils.py,sha256=GUVPrkZfMoAj4MRoBs5BD_7vSuLZTZx69hyWzYFrI50,7747
|
27
27
|
unique_toolkit/embedding/__init__.py,sha256=uUyzjonPvuDCYsvXCIt7ErQXopLggpzX-MEQd3_e2kE,250
|
28
28
|
unique_toolkit/embedding/constants.py,sha256=Lj8-Lcy1FvuC31PM9Exq7vaFuxQV4pEI1huUMFX-J2M,52
|
@@ -48,7 +48,7 @@ unique_toolkit/language_model/__init__.py,sha256=lRQyLlbwHbNFf4-0foBU13UGb09lwEe
|
|
48
48
|
unique_toolkit/language_model/builder.py,sha256=69WCcmkm2rMP2-YEH_EjHiEp6OzwjwCs8VbhjVJaCe0,3168
|
49
49
|
unique_toolkit/language_model/constants.py,sha256=B-topqW0r83dkC_25DeQfnPk3n53qzIHUCBS7YJ0-1U,119
|
50
50
|
unique_toolkit/language_model/functions.py,sha256=koCAfhtkIGSiy8pSdDpIw9xRbwJ20EeLhDQMUXc8KZk,8049
|
51
|
-
unique_toolkit/language_model/infos.py,sha256=
|
51
|
+
unique_toolkit/language_model/infos.py,sha256=peJ4cSJC__jGLWZoOZGRhoersmkwFmclsXTZi-KqYXc,30723
|
52
52
|
unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO8pPIodzN4Q,3991
|
53
53
|
unique_toolkit/language_model/schemas.py,sha256=DJD2aoMfs2Irnc4rzOrVuV4Fbt84LQAiDGG5rse1dgk,12770
|
54
54
|
unique_toolkit/language_model/service.py,sha256=9LS3ouRNtzqZaKrMFagLZS9gBvNC5e46Ut86YWHBBHY,8470
|
@@ -59,7 +59,9 @@ unique_toolkit/short_term_memory/constants.py,sha256=698CL6-wjup2MvU19RxSmQk3gX7
|
|
59
59
|
unique_toolkit/short_term_memory/functions.py,sha256=3WiK-xatY5nh4Dr5zlDUye1k3E6kr41RiscwtTplw5k,4484
|
60
60
|
unique_toolkit/short_term_memory/schemas.py,sha256=OhfcXyF6ACdwIXW45sKzjtZX_gkcJs8FEZXcgQTNenw,1406
|
61
61
|
unique_toolkit/short_term_memory/service.py,sha256=vEKFxP1SScPrFniso492fVthWR1sosdFibhiNF3zRvI,8081
|
62
|
-
unique_toolkit
|
63
|
-
unique_toolkit
|
64
|
-
unique_toolkit-0.7.
|
65
|
-
unique_toolkit-0.7.
|
62
|
+
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
|
+
unique_toolkit/smart_rules/compile.py,sha256=44qDrrKD-bKCjjyUep9qa1IwNkneXoQezfFoVm1QToM,9558
|
64
|
+
unique_toolkit-0.7.26.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
65
|
+
unique_toolkit-0.7.26.dist-info/METADATA,sha256=Au6JVHERLYsvDn8yH4tT_K_aB-fK3RhB83-GMIrIjCc,23803
|
66
|
+
unique_toolkit-0.7.26.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
67
|
+
unique_toolkit-0.7.26.dist-info/RECORD,,
|
File without changes
|
File without changes
|