unique_toolkit 0.7.26__py3-none-any.whl → 0.7.27__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 -0
- unique_toolkit/chat/functions.py +79 -4
- unique_toolkit/chat/service.py +60 -13
- unique_toolkit/language_model/functions.py +142 -9
- unique_toolkit/language_model/reference.py +244 -0
- unique_toolkit/language_model/service.py +57 -1
- unique_toolkit/protocols/support.py +36 -2
- {unique_toolkit-0.7.26.dist-info → unique_toolkit-0.7.27.dist-info}/METADATA +6 -1
- {unique_toolkit-0.7.26.dist-info → unique_toolkit-0.7.27.dist-info}/RECORD +11 -10
- {unique_toolkit-0.7.26.dist-info → unique_toolkit-0.7.27.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.7.26.dist-info → unique_toolkit-0.7.27.dist-info}/WHEEL +0 -0
unique_toolkit/app/schemas.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
import json
|
1
2
|
from enum import StrEnum
|
3
|
+
from pathlib import Path
|
2
4
|
from typing import Any, Optional
|
3
5
|
|
4
6
|
from humps import camelize
|
@@ -27,6 +29,14 @@ class BaseEvent(BaseModel):
|
|
27
29
|
user_id: str
|
28
30
|
company_id: str
|
29
31
|
|
32
|
+
@classmethod
|
33
|
+
def from_json_file(cls, file_path: Path) -> "BaseEvent":
|
34
|
+
if not file_path.exists():
|
35
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
36
|
+
with file_path.open("r", encoding="utf-8") as f:
|
37
|
+
data = json.load(f)
|
38
|
+
return cls.model_validate(data)
|
39
|
+
|
30
40
|
|
31
41
|
###
|
32
42
|
# ChatEvent schemas
|
@@ -140,6 +150,14 @@ class ChatEvent(BaseEvent):
|
|
140
150
|
created_at: Optional[int] = None
|
141
151
|
version: Optional[str] = None
|
142
152
|
|
153
|
+
@classmethod
|
154
|
+
def from_json_file(cls, file_path: Path) -> "ChatEvent":
|
155
|
+
if not file_path.exists():
|
156
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
157
|
+
with file_path.open("r", encoding="utf-8") as f:
|
158
|
+
data = json.load(f)
|
159
|
+
return cls.model_validate(data)
|
160
|
+
|
143
161
|
|
144
162
|
@deprecated(
|
145
163
|
"""Use the more specific `ChatEvent` instead that has the same properties. \
|
@@ -150,3 +168,11 @@ class Event(ChatEvent):
|
|
150
168
|
# The below should only affect type hints
|
151
169
|
# event: EventName T
|
152
170
|
# payload: EventPayload
|
171
|
+
|
172
|
+
@classmethod
|
173
|
+
def from_json_file(cls, file_path: Path) -> "Event":
|
174
|
+
if not file_path.exists():
|
175
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
176
|
+
with file_path.open("r", encoding="utf-8") as f:
|
177
|
+
data = json.load(f)
|
178
|
+
return cls.model_validate(data)
|
unique_toolkit/chat/functions.py
CHANGED
@@ -3,6 +3,7 @@ import re
|
|
3
3
|
from typing import Any, Dict, List, cast
|
4
4
|
|
5
5
|
import unique_sdk
|
6
|
+
from typing_extensions import deprecated
|
6
7
|
from unique_sdk._list_object import ListObject
|
7
8
|
|
8
9
|
from unique_toolkit._common import _time_utils
|
@@ -673,6 +674,7 @@ async def modify_message_assessment_async(
|
|
673
674
|
raise e
|
674
675
|
|
675
676
|
|
677
|
+
@deprecated("Use stream_complete_with_references instead")
|
676
678
|
def stream_complete_to_chat(
|
677
679
|
company_id: str,
|
678
680
|
user_id: str,
|
@@ -682,7 +684,43 @@ def stream_complete_to_chat(
|
|
682
684
|
assistant_id: str,
|
683
685
|
messages: LanguageModelMessages,
|
684
686
|
model_name: LanguageModelName | str,
|
685
|
-
content_chunks: list[ContentChunk] =
|
687
|
+
content_chunks: list[ContentChunk] | None = None,
|
688
|
+
debug_info: dict = {},
|
689
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
690
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
691
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
692
|
+
start_text: str | None = None,
|
693
|
+
other_options: dict | None = None,
|
694
|
+
) -> LanguageModelStreamResponse:
|
695
|
+
return stream_complete_with_references(
|
696
|
+
company_id=company_id,
|
697
|
+
user_id=user_id,
|
698
|
+
assistant_message_id=assistant_message_id,
|
699
|
+
user_message_id=user_message_id,
|
700
|
+
chat_id=chat_id,
|
701
|
+
assistant_id=assistant_id,
|
702
|
+
messages=messages,
|
703
|
+
model_name=model_name,
|
704
|
+
content_chunks=content_chunks,
|
705
|
+
debug_info=debug_info,
|
706
|
+
temperature=temperature,
|
707
|
+
timeout=timeout,
|
708
|
+
tools=tools,
|
709
|
+
start_text=start_text,
|
710
|
+
other_options=other_options,
|
711
|
+
)
|
712
|
+
|
713
|
+
|
714
|
+
def stream_complete_with_references(
|
715
|
+
company_id: str,
|
716
|
+
user_id: str,
|
717
|
+
assistant_message_id: str,
|
718
|
+
user_message_id: str,
|
719
|
+
chat_id: str,
|
720
|
+
assistant_id: str,
|
721
|
+
messages: LanguageModelMessages,
|
722
|
+
model_name: LanguageModelName | str,
|
723
|
+
content_chunks: list[ContentChunk] | None = None,
|
686
724
|
debug_info: dict = {},
|
687
725
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
688
726
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
@@ -719,7 +757,7 @@ def stream_complete_to_chat(
|
|
719
757
|
temperature=temperature,
|
720
758
|
tools=tools,
|
721
759
|
other_options=other_options,
|
722
|
-
content_chunks=content_chunks,
|
760
|
+
content_chunks=content_chunks or [],
|
723
761
|
)
|
724
762
|
|
725
763
|
try:
|
@@ -747,6 +785,7 @@ def stream_complete_to_chat(
|
|
747
785
|
raise e
|
748
786
|
|
749
787
|
|
788
|
+
@deprecated("Use stream_complete_with_references_async instead")
|
750
789
|
async def stream_complete_to_chat_async(
|
751
790
|
company_id: str,
|
752
791
|
user_id: str,
|
@@ -756,7 +795,43 @@ async def stream_complete_to_chat_async(
|
|
756
795
|
assistant_id: str,
|
757
796
|
messages: LanguageModelMessages,
|
758
797
|
model_name: LanguageModelName | str,
|
759
|
-
content_chunks: list[ContentChunk] =
|
798
|
+
content_chunks: list[ContentChunk] | None = None,
|
799
|
+
debug_info: dict = {},
|
800
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
801
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
802
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
803
|
+
start_text: str | None = None,
|
804
|
+
other_options: dict | None = None,
|
805
|
+
) -> LanguageModelStreamResponse:
|
806
|
+
return await stream_complete_with_references_async(
|
807
|
+
company_id=company_id,
|
808
|
+
user_id=user_id,
|
809
|
+
assistant_message_id=assistant_message_id,
|
810
|
+
user_message_id=user_message_id,
|
811
|
+
chat_id=chat_id,
|
812
|
+
assistant_id=assistant_id,
|
813
|
+
messages=messages,
|
814
|
+
model_name=model_name,
|
815
|
+
content_chunks=content_chunks,
|
816
|
+
debug_info=debug_info,
|
817
|
+
temperature=temperature,
|
818
|
+
timeout=timeout,
|
819
|
+
tools=tools,
|
820
|
+
start_text=start_text,
|
821
|
+
other_options=other_options,
|
822
|
+
)
|
823
|
+
|
824
|
+
|
825
|
+
async def stream_complete_with_references_async(
|
826
|
+
company_id: str,
|
827
|
+
user_id: str,
|
828
|
+
assistant_message_id: str,
|
829
|
+
user_message_id: str,
|
830
|
+
chat_id: str,
|
831
|
+
assistant_id: str,
|
832
|
+
messages: LanguageModelMessages,
|
833
|
+
model_name: LanguageModelName | str,
|
834
|
+
content_chunks: list[ContentChunk] | None = None,
|
760
835
|
debug_info: dict = {},
|
761
836
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
762
837
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
@@ -778,7 +853,7 @@ async def stream_complete_to_chat_async(
|
|
778
853
|
temperature=temperature,
|
779
854
|
tools=tools,
|
780
855
|
other_options=other_options,
|
781
|
-
content_chunks=content_chunks,
|
856
|
+
content_chunks=content_chunks or [],
|
782
857
|
)
|
783
858
|
|
784
859
|
try:
|
unique_toolkit/chat/service.py
CHANGED
@@ -48,8 +48,8 @@ from unique_toolkit.language_model.schemas import (
|
|
48
48
|
)
|
49
49
|
|
50
50
|
from .functions import (
|
51
|
-
|
52
|
-
|
51
|
+
stream_complete_with_references,
|
52
|
+
stream_complete_with_references_async,
|
53
53
|
)
|
54
54
|
|
55
55
|
logger = logging.getLogger(f"toolkit.{DOMAIN_NAME}.{__name__}")
|
@@ -1084,11 +1084,36 @@ class ChatService:
|
|
1084
1084
|
label=label,
|
1085
1085
|
)
|
1086
1086
|
|
1087
|
+
@deprecated("Use complete_with_references instead")
|
1087
1088
|
def stream_complete(
|
1088
1089
|
self,
|
1089
1090
|
messages: LanguageModelMessages,
|
1090
1091
|
model_name: LanguageModelName | str,
|
1091
|
-
content_chunks: list[ContentChunk] =
|
1092
|
+
content_chunks: list[ContentChunk] | None = None,
|
1093
|
+
debug_info: dict = {},
|
1094
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
1095
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
1096
|
+
tools: Optional[list[LanguageModelTool | LanguageModelToolDescription]] = None,
|
1097
|
+
start_text: Optional[str] = None,
|
1098
|
+
other_options: Optional[dict] = None,
|
1099
|
+
) -> LanguageModelStreamResponse:
|
1100
|
+
return self.complete_with_references(
|
1101
|
+
messages=messages,
|
1102
|
+
model_name=model_name,
|
1103
|
+
content_chunks=content_chunks,
|
1104
|
+
debug_info=debug_info,
|
1105
|
+
temperature=temperature,
|
1106
|
+
timeout=timeout,
|
1107
|
+
tools=tools,
|
1108
|
+
start_text=start_text,
|
1109
|
+
other_options=other_options,
|
1110
|
+
)
|
1111
|
+
|
1112
|
+
def complete_with_references(
|
1113
|
+
self,
|
1114
|
+
messages: LanguageModelMessages,
|
1115
|
+
model_name: LanguageModelName | str,
|
1116
|
+
content_chunks: list[ContentChunk] | None = None,
|
1092
1117
|
debug_info: dict = {},
|
1093
1118
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
1094
1119
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
@@ -1117,7 +1142,7 @@ class ChatService:
|
|
1117
1142
|
]
|
1118
1143
|
)
|
1119
1144
|
|
1120
|
-
return
|
1145
|
+
return stream_complete_with_references(
|
1121
1146
|
company_id=company_id,
|
1122
1147
|
user_id=user_id,
|
1123
1148
|
assistant_message_id=assistant_message_id,
|
@@ -1139,7 +1164,7 @@ class ChatService:
|
|
1139
1164
|
self,
|
1140
1165
|
messages: LanguageModelMessages,
|
1141
1166
|
model_name: LanguageModelName | str,
|
1142
|
-
content_chunks: list[ContentChunk] =
|
1167
|
+
content_chunks: list[ContentChunk] | None = None,
|
1143
1168
|
debug_info: dict = {},
|
1144
1169
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
1145
1170
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
@@ -1147,7 +1172,7 @@ class ChatService:
|
|
1147
1172
|
start_text: Optional[str] = None,
|
1148
1173
|
other_options: Optional[dict] = None,
|
1149
1174
|
) -> LanguageModelResponse:
|
1150
|
-
response = self.
|
1175
|
+
response = self.complete_with_references(
|
1151
1176
|
messages=messages,
|
1152
1177
|
model_name=model_name,
|
1153
1178
|
content_chunks=content_chunks,
|
@@ -1161,11 +1186,12 @@ class ChatService:
|
|
1161
1186
|
|
1162
1187
|
return LanguageModelResponse.from_stream_response(response)
|
1163
1188
|
|
1189
|
+
@deprecated("use complete_with_references_async instead.")
|
1164
1190
|
async def stream_complete_async(
|
1165
1191
|
self,
|
1166
1192
|
messages: LanguageModelMessages,
|
1167
1193
|
model_name: LanguageModelName | str,
|
1168
|
-
content_chunks: list[ContentChunk] =
|
1194
|
+
content_chunks: list[ContentChunk] | None = None,
|
1169
1195
|
debug_info: dict = {},
|
1170
1196
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
1171
1197
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
@@ -1173,10 +1199,31 @@ class ChatService:
|
|
1173
1199
|
start_text: Optional[str] = None,
|
1174
1200
|
other_options: Optional[dict] = None,
|
1175
1201
|
) -> LanguageModelStreamResponse:
|
1176
|
-
"""
|
1177
|
-
|
1178
|
-
|
1202
|
+
"""Stream a completion in the chat session asynchronously."""
|
1203
|
+
return await self.complete_with_references_async(
|
1204
|
+
messages=messages,
|
1205
|
+
model_name=model_name,
|
1206
|
+
content_chunks=content_chunks,
|
1207
|
+
debug_info=debug_info,
|
1208
|
+
temperature=temperature,
|
1209
|
+
timeout=timeout,
|
1210
|
+
tools=tools,
|
1211
|
+
start_text=start_text,
|
1212
|
+
other_options=other_options,
|
1213
|
+
)
|
1179
1214
|
|
1215
|
+
async def complete_with_references_async(
|
1216
|
+
self,
|
1217
|
+
messages: LanguageModelMessages,
|
1218
|
+
model_name: LanguageModelName | str,
|
1219
|
+
content_chunks: list[ContentChunk] | None = None,
|
1220
|
+
debug_info: dict = {},
|
1221
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
1222
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
1223
|
+
tools: Optional[list[LanguageModelTool | LanguageModelToolDescription]] = None,
|
1224
|
+
start_text: Optional[str] = None,
|
1225
|
+
other_options: Optional[dict] = None,
|
1226
|
+
) -> LanguageModelStreamResponse:
|
1180
1227
|
[
|
1181
1228
|
company_id,
|
1182
1229
|
user_id,
|
@@ -1195,7 +1242,7 @@ class ChatService:
|
|
1195
1242
|
]
|
1196
1243
|
)
|
1197
1244
|
|
1198
|
-
return await
|
1245
|
+
return await stream_complete_with_references_async(
|
1199
1246
|
company_id=company_id,
|
1200
1247
|
user_id=user_id,
|
1201
1248
|
assistant_message_id=assistant_message_id,
|
@@ -1217,7 +1264,7 @@ class ChatService:
|
|
1217
1264
|
self,
|
1218
1265
|
messages: LanguageModelMessages,
|
1219
1266
|
model_name: LanguageModelName | str,
|
1220
|
-
content_chunks: list[ContentChunk]
|
1267
|
+
content_chunks: list[ContentChunk] | None,
|
1221
1268
|
debug_info: dict = {},
|
1222
1269
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
1223
1270
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
@@ -1225,7 +1272,7 @@ class ChatService:
|
|
1225
1272
|
start_text: Optional[str] = None,
|
1226
1273
|
other_options: Optional[dict] = None,
|
1227
1274
|
) -> LanguageModelResponse:
|
1228
|
-
response = self.
|
1275
|
+
response = self.complete_with_references_async(
|
1229
1276
|
messages=messages,
|
1230
1277
|
model_name=model_name,
|
1231
1278
|
content_chunks=content_chunks,
|
@@ -1,23 +1,33 @@
|
|
1
|
+
import copy
|
1
2
|
import logging
|
2
|
-
from
|
3
|
+
from datetime import datetime, timezone
|
4
|
+
from typing import Any, cast
|
3
5
|
|
4
6
|
import unique_sdk
|
5
7
|
from pydantic import BaseModel
|
6
8
|
|
9
|
+
from unique_toolkit.chat.schemas import ChatMessage, ChatMessageRole
|
7
10
|
from unique_toolkit.content.schemas import ContentChunk
|
8
11
|
from unique_toolkit.evaluators import DOMAIN_NAME
|
9
|
-
|
10
|
-
|
11
|
-
DEFAULT_COMPLETE_TEMPERATURE,
|
12
|
-
DEFAULT_COMPLETE_TIMEOUT,
|
13
|
-
)
|
14
|
-
from .infos import LanguageModelName
|
15
|
-
from .schemas import (
|
12
|
+
from unique_toolkit.language_model import (
|
13
|
+
LanguageModelMessageRole,
|
16
14
|
LanguageModelMessages,
|
17
15
|
LanguageModelResponse,
|
16
|
+
LanguageModelStreamResponse,
|
17
|
+
LanguageModelStreamResponseMessage,
|
18
18
|
LanguageModelTool,
|
19
19
|
LanguageModelToolDescription,
|
20
20
|
)
|
21
|
+
from unique_toolkit.language_model.infos import LanguageModelName
|
22
|
+
from unique_toolkit.language_model.reference import (
|
23
|
+
PotentialReference,
|
24
|
+
add_references_to_message,
|
25
|
+
)
|
26
|
+
|
27
|
+
from .constants import (
|
28
|
+
DEFAULT_COMPLETE_TEMPERATURE,
|
29
|
+
DEFAULT_COMPLETE_TIMEOUT,
|
30
|
+
)
|
21
31
|
|
22
32
|
logger = logging.getLogger(f"toolkit.{DOMAIN_NAME}.{__name__}")
|
23
33
|
|
@@ -36,6 +46,7 @@ def complete(
|
|
36
46
|
"""Call the completion endpoint synchronously without streaming the response.
|
37
47
|
|
38
48
|
Args:
|
49
|
+
----
|
39
50
|
company_id (str): The company ID associated with the request.
|
40
51
|
messages (LanguageModelMessages): The messages to complete.
|
41
52
|
model_name (LanguageModelName | str): The model name to use for the completion.
|
@@ -45,6 +56,7 @@ def complete(
|
|
45
56
|
other_options (Optional[dict]): Additional options to use. Defaults to None.
|
46
57
|
|
47
58
|
Returns:
|
59
|
+
-------
|
48
60
|
LanguageModelResponse: The response object containing the completed result.
|
49
61
|
|
50
62
|
"""
|
@@ -93,6 +105,7 @@ async def complete_async(
|
|
93
105
|
the completed result.
|
94
106
|
|
95
107
|
Args:
|
108
|
+
----
|
96
109
|
company_id (str): The company ID associated with the request.
|
97
110
|
messages (LanguageModelMessages): The messages to complete.
|
98
111
|
model_name (LanguageModelName | str): The model name to use for the completion.
|
@@ -102,9 +115,11 @@ async def complete_async(
|
|
102
115
|
other_options (Optional[dict]): The other options to use. Defaults to None.
|
103
116
|
|
104
117
|
Returns:
|
118
|
+
-------
|
105
119
|
LanguageModelResponse: The response object containing the completed result.
|
106
120
|
|
107
121
|
Raises:
|
122
|
+
------
|
108
123
|
Exception: If an error occurs during the request, an exception is raised
|
109
124
|
and logged.
|
110
125
|
|
@@ -198,7 +213,8 @@ def _prepare_completion_params_util(
|
|
198
213
|
) -> tuple[dict, str, dict, dict | None]:
|
199
214
|
"""Prepare common parameters for completion requests.
|
200
215
|
|
201
|
-
Returns
|
216
|
+
Returns
|
217
|
+
-------
|
202
218
|
tuple containing:
|
203
219
|
- options (dict): Combined options including tools and temperature
|
204
220
|
- model (str): Resolved model name
|
@@ -232,3 +248,120 @@ def _prepare_completion_params_util(
|
|
232
248
|
)
|
233
249
|
|
234
250
|
return options, model, messages_dict, search_context
|
251
|
+
|
252
|
+
|
253
|
+
def complete_with_references(
|
254
|
+
company_id: str,
|
255
|
+
messages: LanguageModelMessages,
|
256
|
+
model_name: LanguageModelName | str,
|
257
|
+
content_chunks: list[ContentChunk] | None = None,
|
258
|
+
debug_dict: dict = {},
|
259
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
260
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
261
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
262
|
+
start_text: str | None = None,
|
263
|
+
other_options: dict[str, Any] | None = None,
|
264
|
+
) -> LanguageModelStreamResponse:
|
265
|
+
# Use toolkit language model functions for chat completion
|
266
|
+
response = complete(
|
267
|
+
company_id=company_id,
|
268
|
+
model_name=model_name,
|
269
|
+
messages=messages,
|
270
|
+
temperature=temperature,
|
271
|
+
timeout=timeout,
|
272
|
+
tools=tools,
|
273
|
+
other_options=other_options,
|
274
|
+
)
|
275
|
+
|
276
|
+
return _create_language_model_stream_response_with_references(
|
277
|
+
response=response,
|
278
|
+
content_chunks=content_chunks,
|
279
|
+
start_text=start_text,
|
280
|
+
)
|
281
|
+
|
282
|
+
|
283
|
+
async def complete_with_references_async(
|
284
|
+
company_id: str,
|
285
|
+
messages: LanguageModelMessages,
|
286
|
+
model_name: LanguageModelName | str,
|
287
|
+
content_chunks: list[ContentChunk] | None = None,
|
288
|
+
debug_dict: dict = {},
|
289
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
290
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
291
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
292
|
+
start_text: str | None = None,
|
293
|
+
other_options: dict[str, Any] | None = None,
|
294
|
+
) -> LanguageModelStreamResponse:
|
295
|
+
# Use toolkit language model functions for chat completion
|
296
|
+
response = await complete_async(
|
297
|
+
company_id=company_id,
|
298
|
+
model_name=model_name,
|
299
|
+
messages=messages,
|
300
|
+
temperature=temperature,
|
301
|
+
timeout=timeout,
|
302
|
+
tools=tools,
|
303
|
+
other_options=other_options,
|
304
|
+
)
|
305
|
+
|
306
|
+
return _create_language_model_stream_response_with_references(
|
307
|
+
response=response,
|
308
|
+
content_chunks=content_chunks,
|
309
|
+
start_text=start_text,
|
310
|
+
)
|
311
|
+
|
312
|
+
|
313
|
+
def _create_language_model_stream_response_with_references(
|
314
|
+
response: LanguageModelResponse,
|
315
|
+
content_chunks: list[ContentChunk] | None = None,
|
316
|
+
start_text: str | None = None,
|
317
|
+
):
|
318
|
+
content = response.choices[0].message.content
|
319
|
+
content_chunks = content_chunks or []
|
320
|
+
|
321
|
+
if content is None:
|
322
|
+
raise ValueError("Content is None, which is not supported")
|
323
|
+
elif isinstance(content, list):
|
324
|
+
raise ValueError("Content is a list, which is not supported")
|
325
|
+
else:
|
326
|
+
content = start_text or "" + str(content)
|
327
|
+
|
328
|
+
message = ChatMessage(
|
329
|
+
id="msg_unknown",
|
330
|
+
text=copy.deepcopy(content),
|
331
|
+
role=ChatMessageRole.ASSISTANT,
|
332
|
+
created_at=datetime.now(timezone.utc),
|
333
|
+
chat_id="chat_unknown",
|
334
|
+
)
|
335
|
+
|
336
|
+
search_context = [
|
337
|
+
PotentialReference(
|
338
|
+
id=source.id,
|
339
|
+
chunk_id=source.id,
|
340
|
+
title=source.title,
|
341
|
+
key=source.key or "",
|
342
|
+
url=source.url,
|
343
|
+
)
|
344
|
+
for source in content_chunks
|
345
|
+
]
|
346
|
+
|
347
|
+
message, __ = add_references_to_message(
|
348
|
+
message=message,
|
349
|
+
search_context=search_context,
|
350
|
+
)
|
351
|
+
|
352
|
+
stream_response_message = LanguageModelStreamResponseMessage(
|
353
|
+
id="stream_unknown",
|
354
|
+
previous_message_id=None,
|
355
|
+
role=LanguageModelMessageRole.ASSISTANT,
|
356
|
+
text=message.content or "",
|
357
|
+
original_text=content,
|
358
|
+
references=[u.model_dump() for u in message.references or []],
|
359
|
+
)
|
360
|
+
|
361
|
+
tool_calls = [r.function for r in response.choices[0].message.tool_calls or []]
|
362
|
+
tool_calls = tool_calls if len(tool_calls) > 0 else None
|
363
|
+
|
364
|
+
return LanguageModelStreamResponse(
|
365
|
+
message=stream_response_message,
|
366
|
+
tool_calls=tool_calls,
|
367
|
+
)
|
@@ -0,0 +1,244 @@
|
|
1
|
+
import re
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
from unique_toolkit.chat.schemas import ChatMessage, Reference
|
6
|
+
|
7
|
+
|
8
|
+
class NodeReference(Reference):
|
9
|
+
original_index: list[int] = []
|
10
|
+
message_id: str | None = None
|
11
|
+
|
12
|
+
|
13
|
+
class PotentialReference(BaseModel):
|
14
|
+
id: str
|
15
|
+
chunk_id: str | None = None
|
16
|
+
title: str | None = None
|
17
|
+
key: str
|
18
|
+
url: str | None = None
|
19
|
+
internally_stored_at: str | None = None
|
20
|
+
|
21
|
+
|
22
|
+
def add_references_to_message(
|
23
|
+
message: ChatMessage,
|
24
|
+
search_context: list[PotentialReference],
|
25
|
+
model: str | None = None,
|
26
|
+
) -> tuple[ChatMessage, bool]:
|
27
|
+
"""Add references to a message and return the updated message with change status.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
Tuple[ChatMessage, bool]: (updated_message, references_changed)
|
31
|
+
"""
|
32
|
+
if not message.content:
|
33
|
+
return message, False
|
34
|
+
|
35
|
+
if message.id is None:
|
36
|
+
raise ValueError("Message ID is required")
|
37
|
+
|
38
|
+
message.content = _preprocess_message(message.content)
|
39
|
+
text, ref_found = _add_references(
|
40
|
+
message.content, search_context, message.id, model
|
41
|
+
)
|
42
|
+
message.content = _postprocess_message(text)
|
43
|
+
|
44
|
+
message.references = [Reference(**ref.model_dump()) for ref in ref_found]
|
45
|
+
references_changed = len(ref_found) > 0
|
46
|
+
return message, references_changed
|
47
|
+
|
48
|
+
|
49
|
+
def _add_references(
|
50
|
+
text: str,
|
51
|
+
search_context: list[PotentialReference],
|
52
|
+
message_id: str,
|
53
|
+
model: str | None = None,
|
54
|
+
) -> tuple[str, list[NodeReference]]:
|
55
|
+
"""Add references to text and return the processed text with reference status.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
Tuple[str, bool]: (processed_text, ref_found)
|
59
|
+
"""
|
60
|
+
references = _find_references(
|
61
|
+
text=text,
|
62
|
+
search_context=search_context,
|
63
|
+
message_id=message_id,
|
64
|
+
)
|
65
|
+
|
66
|
+
# Only reference a source once, even if it is mentioned multiple times in the text.
|
67
|
+
with_footnotes = _add_footnotes_to_text(text=text, references=references)
|
68
|
+
|
69
|
+
# Gemini 2.5 flash model has tendency to add multiple references for the same fact
|
70
|
+
# This is a workaround to limit the number of references to 5
|
71
|
+
if model and model.startswith("litellm:gemini-2-5-flash"):
|
72
|
+
reduced_text = _limit_consecutive_source_references(with_footnotes)
|
73
|
+
|
74
|
+
# Get the references that remain after reduction
|
75
|
+
remaining_numbers = set()
|
76
|
+
sup_matches = re.findall(r"<sup>(\d+)</sup>", reduced_text)
|
77
|
+
remaining_numbers = {int(match) for match in sup_matches}
|
78
|
+
|
79
|
+
references = [
|
80
|
+
ref for ref in references if ref.sequence_number in remaining_numbers
|
81
|
+
]
|
82
|
+
text = _remove_hallucinated_references(reduced_text)
|
83
|
+
else:
|
84
|
+
text = _remove_hallucinated_references(with_footnotes)
|
85
|
+
|
86
|
+
return text, references
|
87
|
+
|
88
|
+
|
89
|
+
def _preprocess_message(text: str) -> str:
|
90
|
+
"""Preprocess message text to normalize reference formats."""
|
91
|
+
# Remove user & assistant references: XML format '[<user>]', '[\<user>]', etc.
|
92
|
+
patterns = [
|
93
|
+
(r"\[(\\)?(<)?user(>)?\]", ""),
|
94
|
+
(r"\[(\\)?(<)?assistant(>)?\]", ""),
|
95
|
+
(r"source[\s]?\[(\\)?(<)?conversation(>)?\]", "the previous conversation"),
|
96
|
+
(r"\[(\\)?(<)?previous[_,\s]conversation(>)?\]", ""),
|
97
|
+
(r"\[(\\)?(<)?past[_,\s]conversation(>)?\]", ""),
|
98
|
+
(r"\[(\\)?(<)?previous[_,\s]?answer(>)?\]", ""),
|
99
|
+
(r"\[(\\)?(<)?previous[_,\s]question(>)?\]", ""),
|
100
|
+
(r"\[(\\)?(<)?conversation(>)?\]", ""),
|
101
|
+
(r"\[(\\)?(<)?none(>)?\]", ""),
|
102
|
+
]
|
103
|
+
|
104
|
+
for pattern, replacement in patterns:
|
105
|
+
text = re.sub(pattern, replacement, text, flags=re.IGNORECASE)
|
106
|
+
|
107
|
+
# Replace XML format '[<source XX>]', '[<sourceXX>]' and '[\<sourceXX>]' with [XX]
|
108
|
+
text = re.sub(r"\[(\\)?<source[\s]?(\d+)>\]", r"[\2]", text)
|
109
|
+
|
110
|
+
# Replace format '[source XX]' and '[sourceXX]' with [XX]
|
111
|
+
text = re.sub(r"\[source[\s]?(\d+)\]", r"[\1]", text)
|
112
|
+
|
113
|
+
# Make all references non-bold
|
114
|
+
text = re.sub(r"\[\*\*(\d+)\*\*\]", r"[\1]", text)
|
115
|
+
|
116
|
+
# Replace 'SOURCEXX' and 'SOURCE XX' with [XX]
|
117
|
+
text = re.sub(r"source[\s]?(\d+)", r"[\1]", text, flags=re.IGNORECASE)
|
118
|
+
|
119
|
+
# Replace 'SOURCE n°X' with [XX]
|
120
|
+
text = re.sub(r"source[\s]?n°(\d+)", r"[\1]", text, flags=re.IGNORECASE)
|
121
|
+
|
122
|
+
# Replace '[<[XX]>]' and '[\<[XX]>]' with [XX]
|
123
|
+
text = re.sub(r"\[(\\)?\[?<\[(\d+)\]?\]>\]", r"[\2]", text)
|
124
|
+
|
125
|
+
# Replace '[[A], [B], ...]' or '[[A], B, C, ...]' with [A][B][C]...
|
126
|
+
def replace_combined_brackets(match):
|
127
|
+
numbers = re.findall(r"\d+", match.group(0))
|
128
|
+
return "".join(f"[{n}]" for n in numbers)
|
129
|
+
|
130
|
+
text = re.sub(
|
131
|
+
r"\[\[(\d+)\](?:,\s*(?:\[)?\d+(?:\])?)*\]", replace_combined_brackets, text
|
132
|
+
)
|
133
|
+
|
134
|
+
return text
|
135
|
+
|
136
|
+
|
137
|
+
def _limit_consecutive_source_references(text: str) -> str:
|
138
|
+
"""Limit consecutive source references to maximum 5 unique sources."""
|
139
|
+
|
140
|
+
def replace_consecutive(match):
|
141
|
+
# Extract all numbers from the match and get unique values
|
142
|
+
numbers = list(set(re.findall(r"\d+", match.group(0))))
|
143
|
+
# Take only the first five unique numbers
|
144
|
+
return "".join(f"<sup>{n}</sup>" for n in numbers[:5])
|
145
|
+
|
146
|
+
# Find sequences of 5+ consecutive sources
|
147
|
+
pattern = r"(?:<sup>\d+</sup>){5,}"
|
148
|
+
return re.sub(pattern, replace_consecutive, text)
|
149
|
+
|
150
|
+
|
151
|
+
def _postprocess_message(text: str) -> str:
|
152
|
+
"""Format superscript references to remove duplicates."""
|
153
|
+
|
154
|
+
def replace_sup_sequence(match):
|
155
|
+
# Extract unique numbers from the entire match
|
156
|
+
sup_numbers = set(re.findall(r"\d+", match.group(0)))
|
157
|
+
return "".join(f"<sup>{n}</sup>" for n in sup_numbers)
|
158
|
+
|
159
|
+
# Find sequences of 2+ superscripts including internal spaces
|
160
|
+
pattern = r"(<sup>\d+</sup>[ ]*)+<sup>\d+</sup>"
|
161
|
+
return re.sub(pattern, replace_sup_sequence, text)
|
162
|
+
|
163
|
+
|
164
|
+
def _get_max_sub_count_in_text(text: str) -> int:
|
165
|
+
"""Get the maximum superscript number in the text."""
|
166
|
+
matches = re.findall(r"<sup>(\d+)</sup>", text)
|
167
|
+
return max((int(match) for match in matches), default=0)
|
168
|
+
|
169
|
+
|
170
|
+
def _find_references(
|
171
|
+
text: str,
|
172
|
+
search_context: list[PotentialReference],
|
173
|
+
message_id: str,
|
174
|
+
) -> list[NodeReference]:
|
175
|
+
"""Find references in text based on search context."""
|
176
|
+
references: list[NodeReference] = []
|
177
|
+
sequence_number = 1 + _get_max_sub_count_in_text(text)
|
178
|
+
|
179
|
+
# Find all numbers in brackets to ensure we get references in order of occurrence
|
180
|
+
numbers_in_brackets = _extract_numbers_in_brackets(text)
|
181
|
+
|
182
|
+
for number in numbers_in_brackets:
|
183
|
+
# Convert 1-based reference to 0-based index
|
184
|
+
index = number - 1
|
185
|
+
if index < 0 or index >= len(search_context):
|
186
|
+
continue
|
187
|
+
|
188
|
+
search = search_context[index]
|
189
|
+
if not search:
|
190
|
+
continue
|
191
|
+
|
192
|
+
# Don't put the reference twice
|
193
|
+
reference_name = search.title or search.key
|
194
|
+
found_reference = next(
|
195
|
+
(r for r in references if r.name == reference_name), None
|
196
|
+
)
|
197
|
+
|
198
|
+
if found_reference:
|
199
|
+
found_reference.original_index.append(number)
|
200
|
+
continue
|
201
|
+
|
202
|
+
url = (
|
203
|
+
search.url
|
204
|
+
if search.url and not search.internally_stored_at
|
205
|
+
else f"unique://content/{search.id}"
|
206
|
+
)
|
207
|
+
|
208
|
+
references.append(
|
209
|
+
NodeReference(
|
210
|
+
name=reference_name,
|
211
|
+
url=url,
|
212
|
+
sequence_number=sequence_number,
|
213
|
+
original_index=[number],
|
214
|
+
source_id=f"{search.id}_{search.chunk_id}"
|
215
|
+
if search.chunk_id
|
216
|
+
else search.id,
|
217
|
+
source="node-ingestion-chunks",
|
218
|
+
message_id=message_id,
|
219
|
+
)
|
220
|
+
)
|
221
|
+
sequence_number += 1
|
222
|
+
|
223
|
+
return references
|
224
|
+
|
225
|
+
|
226
|
+
def _extract_numbers_in_brackets(text: str) -> list[int]:
|
227
|
+
"""Extract numbers from [X] format in text."""
|
228
|
+
matches = re.findall(r"\[(\d+)\]", text)
|
229
|
+
return [int(match) for match in matches]
|
230
|
+
|
231
|
+
|
232
|
+
def _add_footnotes_to_text(text: str, references: list[NodeReference]) -> str:
|
233
|
+
"""Replace bracket references with superscript footnotes."""
|
234
|
+
for reference in references:
|
235
|
+
for original_index in reference.original_index:
|
236
|
+
text = text.replace(
|
237
|
+
f"[{original_index}]", f"<sup>{reference.sequence_number}</sup>"
|
238
|
+
)
|
239
|
+
return text
|
240
|
+
|
241
|
+
|
242
|
+
def _remove_hallucinated_references(text: str) -> str:
|
243
|
+
"""Remove any remaining bracket references that weren't converted."""
|
244
|
+
return re.sub(r"\[\d+\]", "", text).strip()
|
@@ -1,11 +1,12 @@
|
|
1
1
|
import logging
|
2
|
-
from typing import Optional, Type
|
2
|
+
from typing import Any, Optional, Type
|
3
3
|
|
4
4
|
from pydantic import BaseModel
|
5
5
|
from typing_extensions import deprecated
|
6
6
|
|
7
7
|
from unique_toolkit._common.validate_required_values import validate_required_values
|
8
8
|
from unique_toolkit.app.schemas import BaseEvent, ChatEvent, Event
|
9
|
+
from unique_toolkit.content.schemas import ContentChunk
|
9
10
|
from unique_toolkit.language_model.constants import (
|
10
11
|
DEFAULT_COMPLETE_TEMPERATURE,
|
11
12
|
DEFAULT_COMPLETE_TIMEOUT,
|
@@ -14,11 +15,14 @@ from unique_toolkit.language_model.constants import (
|
|
14
15
|
from unique_toolkit.language_model.functions import (
|
15
16
|
complete,
|
16
17
|
complete_async,
|
18
|
+
complete_with_references,
|
19
|
+
complete_with_references_async,
|
17
20
|
)
|
18
21
|
from unique_toolkit.language_model.infos import LanguageModelName
|
19
22
|
from unique_toolkit.language_model.schemas import (
|
20
23
|
LanguageModelMessages,
|
21
24
|
LanguageModelResponse,
|
25
|
+
LanguageModelStreamResponse,
|
22
26
|
LanguageModelTool,
|
23
27
|
LanguageModelToolDescription,
|
24
28
|
)
|
@@ -260,3 +264,55 @@ class LanguageModelService:
|
|
260
264
|
structured_output_model=structured_output_model,
|
261
265
|
structured_output_enforce_schema=structured_output_enforce_schema,
|
262
266
|
)
|
267
|
+
|
268
|
+
def complete_with_references(
|
269
|
+
self,
|
270
|
+
messages: LanguageModelMessages,
|
271
|
+
model_name: LanguageModelName | str,
|
272
|
+
content_chunks: list[ContentChunk] | None = None,
|
273
|
+
debug_info: dict = {},
|
274
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
275
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
276
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
277
|
+
start_text: str | None = None,
|
278
|
+
other_options: dict[str, Any] | None = None,
|
279
|
+
) -> LanguageModelStreamResponse:
|
280
|
+
[company_id] = validate_required_values([self._company_id])
|
281
|
+
|
282
|
+
return complete_with_references(
|
283
|
+
company_id=company_id,
|
284
|
+
messages=messages,
|
285
|
+
model_name=model_name,
|
286
|
+
content_chunks=content_chunks,
|
287
|
+
temperature=temperature,
|
288
|
+
timeout=timeout,
|
289
|
+
other_options=other_options,
|
290
|
+
tools=tools,
|
291
|
+
start_text=start_text,
|
292
|
+
)
|
293
|
+
|
294
|
+
async def complete_with_references_async(
|
295
|
+
self,
|
296
|
+
messages: LanguageModelMessages,
|
297
|
+
model_name: LanguageModelName | str,
|
298
|
+
content_chunks: list[ContentChunk] | None = None,
|
299
|
+
debug_info: dict = {},
|
300
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
301
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
302
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
303
|
+
start_text: str | None = None,
|
304
|
+
other_options: dict[str, Any] | None = None,
|
305
|
+
) -> LanguageModelStreamResponse:
|
306
|
+
[company_id] = validate_required_values([self._company_id])
|
307
|
+
|
308
|
+
return await complete_with_references_async(
|
309
|
+
company_id=company_id,
|
310
|
+
messages=messages,
|
311
|
+
model_name=model_name,
|
312
|
+
content_chunks=content_chunks,
|
313
|
+
temperature=temperature,
|
314
|
+
timeout=timeout,
|
315
|
+
other_options=other_options,
|
316
|
+
tools=tools,
|
317
|
+
start_text=start_text,
|
318
|
+
)
|
@@ -1,9 +1,11 @@
|
|
1
|
-
from typing import Protocol
|
1
|
+
from typing import Any, Awaitable, Protocol
|
2
2
|
|
3
|
+
from unique_toolkit.content import ContentChunk
|
3
4
|
from unique_toolkit.language_model import (
|
4
5
|
LanguageModelMessages,
|
5
6
|
LanguageModelName,
|
6
7
|
LanguageModelResponse,
|
8
|
+
LanguageModelStreamResponse,
|
7
9
|
LanguageModelTool,
|
8
10
|
LanguageModelToolDescription,
|
9
11
|
)
|
@@ -25,5 +27,37 @@ class SupportsComplete(Protocol):
|
|
25
27
|
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
26
28
|
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
27
29
|
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
28
|
-
**kwargs,
|
29
30
|
) -> LanguageModelResponse: ...
|
31
|
+
|
32
|
+
async def complete_async(
|
33
|
+
self,
|
34
|
+
messages: LanguageModelMessages,
|
35
|
+
model_name: LanguageModelName | str,
|
36
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
37
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
38
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
39
|
+
) -> Awaitable[LanguageModelResponse]: ...
|
40
|
+
|
41
|
+
|
42
|
+
class SupportCompleteWithReferences(Protocol):
|
43
|
+
def complete_with_references(
|
44
|
+
self,
|
45
|
+
messages: LanguageModelMessages,
|
46
|
+
model_name: LanguageModelName | str,
|
47
|
+
content_chunks: list[ContentChunk] | None = None,
|
48
|
+
debug_info: dict[str, Any] = {},
|
49
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
50
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
51
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
52
|
+
) -> LanguageModelStreamResponse: ...
|
53
|
+
|
54
|
+
def complete_with_references_async(
|
55
|
+
self,
|
56
|
+
messages: LanguageModelMessages,
|
57
|
+
model_name: LanguageModelName | str,
|
58
|
+
content_chunks: list[ContentChunk] | None = None,
|
59
|
+
debug_info: dict[str, Any] = {},
|
60
|
+
temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
|
61
|
+
timeout: int = DEFAULT_COMPLETE_TIMEOUT,
|
62
|
+
tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
|
63
|
+
) -> Awaitable[LanguageModelStreamResponse]: ...
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: unique_toolkit
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.27
|
4
4
|
Summary:
|
5
5
|
License: Proprietary
|
6
6
|
Author: Martin Fadler
|
@@ -112,6 +112,11 @@ 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
114
|
|
115
|
+
## [0.7.27] - 2025-06-16
|
116
|
+
- Introduce a protocol for `complete_with_references` to enable testable services
|
117
|
+
- Rename/Create functions `stream_complete` in chat service and llm service accordingly
|
118
|
+
|
119
|
+
|
115
120
|
## [0.7.26] - 2025-06-05
|
116
121
|
- Add `scope_rules` to `ChatEventPayload`
|
117
122
|
- Added `UniqueQL` compiler and pydantic classes for `UniqueQL`. Note this is functionally equivalent but not identical to `UQLOperator` or `UQLCombinator` in `unique_sdk`.
|
@@ -9,13 +9,13 @@ 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=_xQbgKxUtrFGoYb37aWQEZ2mi2gTyqKBGUeDWSLAj8Q,4935
|
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
|
16
|
-
unique_toolkit/chat/functions.py,sha256=
|
16
|
+
unique_toolkit/chat/functions.py,sha256=QsJVhBXgK6jDWRYpEAt-22jy5NKGsYs4fmHrOEdHAyc,29865
|
17
17
|
unique_toolkit/chat/schemas.py,sha256=ct3BbvdQmpcNeDmJdc-Iz33LX1_3O-SGVgrsuT0B99k,2881
|
18
|
-
unique_toolkit/chat/service.py,sha256=
|
18
|
+
unique_toolkit/chat/service.py,sha256=jAgInqq7wU-erezl-BOS9BQ3DOR1nrbVFlMfACn26XI,42827
|
19
19
|
unique_toolkit/chat/state.py,sha256=Cjgwv_2vhDFbV69xxsn7SefhaoIAEqLx3ferdVFCnOg,1445
|
20
20
|
unique_toolkit/chat/utils.py,sha256=ihm-wQykBWhB4liR3LnwPVPt_qGW6ETq21Mw4HY0THE,854
|
21
21
|
unique_toolkit/content/__init__.py,sha256=EdJg_A_7loEtCQf4cah3QARQreJx6pdz89Rm96YbMVg,940
|
@@ -47,13 +47,14 @@ unique_toolkit/evaluators/schemas.py,sha256=Jaue6Uhx75X1CyHKWj8sT3RE1JZXTqoLtfLt
|
|
47
47
|
unique_toolkit/language_model/__init__.py,sha256=lRQyLlbwHbNFf4-0foBU13UGb09lwEeodbVsfsSgaCk,1971
|
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
|
-
unique_toolkit/language_model/functions.py,sha256=
|
50
|
+
unique_toolkit/language_model/functions.py,sha256=J54mzKs-uOBejpiMDa1YviKvJDcYl0gvEF1CfLb7_S4,12208
|
51
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
|
+
unique_toolkit/language_model/reference.py,sha256=TrRfnxd-cjpdijmZ1dKII87aEACIbW7iU_cE9gtGuH4,8314
|
53
54
|
unique_toolkit/language_model/schemas.py,sha256=DJD2aoMfs2Irnc4rzOrVuV4Fbt84LQAiDGG5rse1dgk,12770
|
54
|
-
unique_toolkit/language_model/service.py,sha256=
|
55
|
+
unique_toolkit/language_model/service.py,sha256=PJ0vOGPxzqsQXTQma8blLT4DfGP4gVZVcX2v1GVYozI,10610
|
55
56
|
unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
|
56
|
-
unique_toolkit/protocols/support.py,sha256=
|
57
|
+
unique_toolkit/protocols/support.py,sha256=V15WEIFKVMyF1QCnR8vIi4GrJy4dfTCB6d6JlqPZ58o,2341
|
57
58
|
unique_toolkit/short_term_memory/__init__.py,sha256=2mI3AUrffgH7Yt-xS57EGqnHf7jnn6xquoKEhJqk3Wg,185
|
58
59
|
unique_toolkit/short_term_memory/constants.py,sha256=698CL6-wjup2MvU19RxSmQk3gX7aqW_OOpZB7sbz_Xg,34
|
59
60
|
unique_toolkit/short_term_memory/functions.py,sha256=3WiK-xatY5nh4Dr5zlDUye1k3E6kr41RiscwtTplw5k,4484
|
@@ -61,7 +62,7 @@ unique_toolkit/short_term_memory/schemas.py,sha256=OhfcXyF6ACdwIXW45sKzjtZX_gkcJ
|
|
61
62
|
unique_toolkit/short_term_memory/service.py,sha256=vEKFxP1SScPrFniso492fVthWR1sosdFibhiNF3zRvI,8081
|
62
63
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
64
|
unique_toolkit/smart_rules/compile.py,sha256=44qDrrKD-bKCjjyUep9qa1IwNkneXoQezfFoVm1QToM,9558
|
64
|
-
unique_toolkit-0.7.
|
65
|
-
unique_toolkit-0.7.
|
66
|
-
unique_toolkit-0.7.
|
67
|
-
unique_toolkit-0.7.
|
65
|
+
unique_toolkit-0.7.27.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
66
|
+
unique_toolkit-0.7.27.dist-info/METADATA,sha256=Mh1lDoLWEiOU-0pEXDjd5kOBAgTJjqEagmhW2Hj2RLA,24000
|
67
|
+
unique_toolkit-0.7.27.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
68
|
+
unique_toolkit-0.7.27.dist-info/RECORD,,
|
File without changes
|
File without changes
|