unique_toolkit 0.7.30__py3-none-any.whl → 0.7.32__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/chat/schemas.py +3 -10
- unique_toolkit/content/schemas.py +12 -2
- unique_toolkit/language_model/functions.py +5 -15
- unique_toolkit/language_model/reference.py +14 -28
- unique_toolkit/language_model/schemas.py +36 -1
- {unique_toolkit-0.7.30.dist-info → unique_toolkit-0.7.32.dist-info}/METADATA +9 -2
- {unique_toolkit-0.7.30.dist-info → unique_toolkit-0.7.32.dist-info}/RECORD +9 -9
- {unique_toolkit-0.7.30.dist-info → unique_toolkit-0.7.32.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.7.30.dist-info → unique_toolkit-0.7.32.dist-info}/WHEEL +0 -0
unique_toolkit/chat/schemas.py
CHANGED
@@ -10,6 +10,8 @@ from pydantic import (
|
|
10
10
|
model_validator,
|
11
11
|
)
|
12
12
|
|
13
|
+
from unique_toolkit.content.schemas import ContentReference
|
14
|
+
|
13
15
|
# set config to convert camelCase to snake_case
|
14
16
|
model_config = ConfigDict(
|
15
17
|
alias_generator=camelize, populate_by_name=True, arbitrary_types_allowed=True
|
@@ -37,15 +39,6 @@ class ToolCall(BaseModel):
|
|
37
39
|
function: Function
|
38
40
|
|
39
41
|
|
40
|
-
class Reference(BaseModel):
|
41
|
-
model_config = model_config
|
42
|
-
name: str
|
43
|
-
url: str | None = None
|
44
|
-
sequence_number: int
|
45
|
-
source_id: str
|
46
|
-
source: str
|
47
|
-
|
48
|
-
|
49
42
|
class ChatMessage(BaseModel):
|
50
43
|
# This model should strictly meets https://github.com/Unique-AG/monorepo/blob/master/node/apps/node-chat/src/public-api/2023-12-06/dtos/message/public-message.dto.ts
|
51
44
|
model_config = model_config
|
@@ -63,7 +56,7 @@ class ChatMessage(BaseModel):
|
|
63
56
|
created_at: datetime | None = None
|
64
57
|
completed_at: datetime | None = None
|
65
58
|
updated_at: datetime | None = None
|
66
|
-
references: list[
|
59
|
+
references: list[ContentReference] | None = None
|
67
60
|
|
68
61
|
# TODO make sdk return role consistently in lowercase
|
69
62
|
# Currently needed as sdk returns role in uppercase
|
@@ -60,13 +60,23 @@ class Content(BaseModel):
|
|
60
60
|
|
61
61
|
class ContentReference(BaseModel):
|
62
62
|
model_config = model_config
|
63
|
-
id: str
|
64
|
-
|
63
|
+
id: str = Field(
|
64
|
+
default="",
|
65
|
+
description="The id of the content reference. Can be empty on the ChatMessage Object",
|
66
|
+
)
|
67
|
+
message_id: str = Field(
|
68
|
+
default="",
|
69
|
+
description="The id of the message that this reference belongs to. Can be empty on the ChatMessage Object",
|
70
|
+
)
|
65
71
|
name: str
|
66
72
|
sequence_number: int
|
67
73
|
source: str
|
68
74
|
source_id: str
|
69
75
|
url: str
|
76
|
+
original_index: list[int] = Field(
|
77
|
+
default=[],
|
78
|
+
description="List of indices in the ChatMessage original_content this reference refers to. This is usually the id in the functionCallResponse. List type due to implementation in node-chat",
|
79
|
+
)
|
70
80
|
|
71
81
|
|
72
82
|
class ContentSearchType(StrEnum):
|
@@ -7,7 +7,7 @@ import unique_sdk
|
|
7
7
|
from pydantic import BaseModel
|
8
8
|
|
9
9
|
from unique_toolkit.chat.schemas import ChatMessage, ChatMessageRole
|
10
|
-
from unique_toolkit.content.schemas import ContentChunk
|
10
|
+
from unique_toolkit.content.schemas import ContentChunk, ContentReference
|
11
11
|
from unique_toolkit.evaluators import DOMAIN_NAME
|
12
12
|
from unique_toolkit.language_model import (
|
13
13
|
LanguageModelMessageRole,
|
@@ -20,7 +20,6 @@ from unique_toolkit.language_model import (
|
|
20
20
|
)
|
21
21
|
from unique_toolkit.language_model.infos import LanguageModelName
|
22
22
|
from unique_toolkit.language_model.reference import (
|
23
|
-
PotentialReference,
|
24
23
|
add_references_to_message,
|
25
24
|
)
|
26
25
|
|
@@ -333,20 +332,9 @@ def _create_language_model_stream_response_with_references(
|
|
333
332
|
chat_id="chat_unknown",
|
334
333
|
)
|
335
334
|
|
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
335
|
message, __ = add_references_to_message(
|
348
336
|
message=message,
|
349
|
-
search_context=
|
337
|
+
search_context=content_chunks,
|
350
338
|
)
|
351
339
|
|
352
340
|
stream_response_message = LanguageModelStreamResponseMessage(
|
@@ -355,7 +343,9 @@ def _create_language_model_stream_response_with_references(
|
|
355
343
|
role=LanguageModelMessageRole.ASSISTANT,
|
356
344
|
text=message.content or "",
|
357
345
|
original_text=content,
|
358
|
-
references=[
|
346
|
+
references=[
|
347
|
+
ContentReference(**u.model_dump()) for u in message.references or []
|
348
|
+
],
|
359
349
|
)
|
360
350
|
|
361
351
|
tool_calls = [r.function for r in response.choices[0].message.tool_calls or []]
|
@@ -1,27 +1,12 @@
|
|
1
1
|
import re
|
2
2
|
|
3
|
-
from
|
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
|
3
|
+
from unique_toolkit.chat.schemas import ChatMessage
|
4
|
+
from unique_toolkit.content.schemas import ContentChunk, ContentReference
|
20
5
|
|
21
6
|
|
22
7
|
def add_references_to_message(
|
23
8
|
message: ChatMessage,
|
24
|
-
search_context: list[
|
9
|
+
search_context: list[ContentChunk],
|
25
10
|
model: str | None = None,
|
26
11
|
) -> tuple[ChatMessage, bool]:
|
27
12
|
"""Add references to a message and return the updated message with change status.
|
@@ -41,21 +26,21 @@ def add_references_to_message(
|
|
41
26
|
)
|
42
27
|
message.content = _postprocess_message(text)
|
43
28
|
|
44
|
-
message.references =
|
29
|
+
message.references = ref_found
|
45
30
|
references_changed = len(ref_found) > 0
|
46
31
|
return message, references_changed
|
47
32
|
|
48
33
|
|
49
34
|
def _add_references(
|
50
35
|
text: str,
|
51
|
-
search_context: list[
|
36
|
+
search_context: list[ContentChunk],
|
52
37
|
message_id: str,
|
53
38
|
model: str | None = None,
|
54
|
-
) -> tuple[str, list[
|
39
|
+
) -> tuple[str, list[ContentReference]]:
|
55
40
|
"""Add references to text and return the processed text with reference status.
|
56
41
|
|
57
42
|
Returns:
|
58
|
-
Tuple[str,
|
43
|
+
Tuple[str, list[Reference]]: (processed_text, ref_found)
|
59
44
|
"""
|
60
45
|
references = _find_references(
|
61
46
|
text=text,
|
@@ -169,11 +154,11 @@ def _get_max_sub_count_in_text(text: str) -> int:
|
|
169
154
|
|
170
155
|
def _find_references(
|
171
156
|
text: str,
|
172
|
-
search_context: list[
|
157
|
+
search_context: list[ContentChunk],
|
173
158
|
message_id: str,
|
174
|
-
) -> list[
|
159
|
+
) -> list[ContentReference]:
|
175
160
|
"""Find references in text based on search context."""
|
176
|
-
references: list[
|
161
|
+
references: list[ContentReference] = []
|
177
162
|
sequence_number = 1 + _get_max_sub_count_in_text(text)
|
178
163
|
|
179
164
|
# Find all numbers in brackets to ensure we get references in order of occurrence
|
@@ -190,7 +175,7 @@ def _find_references(
|
|
190
175
|
continue
|
191
176
|
|
192
177
|
# Don't put the reference twice
|
193
|
-
reference_name = search.title or search.key
|
178
|
+
reference_name = search.title or search.key or f"Content {search.id}"
|
194
179
|
found_reference = next(
|
195
180
|
(r for r in references if r.name == reference_name), None
|
196
181
|
)
|
@@ -206,7 +191,7 @@ def _find_references(
|
|
206
191
|
)
|
207
192
|
|
208
193
|
references.append(
|
209
|
-
|
194
|
+
ContentReference(
|
210
195
|
name=reference_name,
|
211
196
|
url=url,
|
212
197
|
sequence_number=sequence_number,
|
@@ -216,6 +201,7 @@ def _find_references(
|
|
216
201
|
else search.id,
|
217
202
|
source="node-ingestion-chunks",
|
218
203
|
message_id=message_id,
|
204
|
+
id=search.id,
|
219
205
|
)
|
220
206
|
)
|
221
207
|
sequence_number += 1
|
@@ -229,7 +215,7 @@ def _extract_numbers_in_brackets(text: str) -> list[int]:
|
|
229
215
|
return [int(match) for match in matches]
|
230
216
|
|
231
217
|
|
232
|
-
def _add_footnotes_to_text(text: str, references: list[
|
218
|
+
def _add_footnotes_to_text(text: str, references: list[ContentReference]) -> str:
|
233
219
|
"""Replace bracket references with superscript footnotes."""
|
234
220
|
for reference in references:
|
235
221
|
for original_index in reference.original_index:
|
@@ -18,6 +18,7 @@ from pydantic import (
|
|
18
18
|
)
|
19
19
|
from typing_extensions import deprecated
|
20
20
|
|
21
|
+
from unique_toolkit.content.schemas import ContentReference
|
21
22
|
from unique_toolkit.language_model.utils import format_message
|
22
23
|
|
23
24
|
# set config to convert camelCase to snake_case
|
@@ -48,7 +49,7 @@ class LanguageModelStreamResponseMessage(BaseModel):
|
|
48
49
|
role: LanguageModelMessageRole
|
49
50
|
text: str
|
50
51
|
original_text: str | None = None
|
51
|
-
references: list[
|
52
|
+
references: list[ContentReference] = []
|
52
53
|
|
53
54
|
# TODO make sdk return role in lowercase
|
54
55
|
# Currently needed as sdk returns role in uppercase
|
@@ -242,6 +243,40 @@ class LanguageModelMessages(RootModel):
|
|
242
243
|
| LanguageModelUserMessage
|
243
244
|
]
|
244
245
|
|
246
|
+
@classmethod
|
247
|
+
def load_messages_to_root(cls, data: list[dict] | dict) -> Self:
|
248
|
+
"""Convert list of dictionaries to appropriate message objects based on role."""
|
249
|
+
# Handle case where data is already wrapped in root
|
250
|
+
if isinstance(data, dict) and "root" in data:
|
251
|
+
messages_list = data["root"]
|
252
|
+
elif isinstance(data, list):
|
253
|
+
messages_list = data
|
254
|
+
else:
|
255
|
+
raise ValueError("Invalid data type")
|
256
|
+
|
257
|
+
# Convert the messages list
|
258
|
+
converted_messages = []
|
259
|
+
for item in messages_list:
|
260
|
+
if isinstance(item, dict):
|
261
|
+
role = item.get("role", "").lower()
|
262
|
+
|
263
|
+
# Map dictionary to appropriate message class based on role
|
264
|
+
if role == "system":
|
265
|
+
converted_messages.append(LanguageModelSystemMessage(**item))
|
266
|
+
elif role == "user":
|
267
|
+
converted_messages.append(LanguageModelUserMessage(**item))
|
268
|
+
elif role == "assistant":
|
269
|
+
converted_messages.append(LanguageModelAssistantMessage(**item))
|
270
|
+
elif role == "tool":
|
271
|
+
converted_messages.append(LanguageModelToolMessage(**item))
|
272
|
+
else:
|
273
|
+
# Fallback to base LanguageModelMessage
|
274
|
+
converted_messages.append(LanguageModelMessage(**item))
|
275
|
+
else:
|
276
|
+
# If it's already a message object, keep it as is
|
277
|
+
converted_messages.append(item)
|
278
|
+
return cls(root=converted_messages)
|
279
|
+
|
245
280
|
def __str__(self):
|
246
281
|
return "\n\n".join([str(message) for message in self.root])
|
247
282
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: unique_toolkit
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.32
|
4
4
|
Summary:
|
5
5
|
License: Proprietary
|
6
6
|
Author: Martin Fadler
|
@@ -17,7 +17,7 @@ Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
|
17
17
|
Requires-Dist: regex (>=2024.5.15,<2025.0.0)
|
18
18
|
Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
|
19
19
|
Requires-Dist: typing-extensions (>=4.9.0,<5.0.0)
|
20
|
-
Requires-Dist: unique-sdk (>=0.9.
|
20
|
+
Requires-Dist: unique-sdk (>=0.9.36,<0.10.0)
|
21
21
|
Description-Content-Type: text/markdown
|
22
22
|
|
23
23
|
# Unique Toolkit
|
@@ -111,6 +111,13 @@ 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
|
+
## [0.7.32] - 2025-06-24
|
115
|
+
- Create `classmethod` for `LanguageModelMessages` to load raw messages to root
|
116
|
+
|
117
|
+
## [0.7.31] - 2025-06-19
|
118
|
+
- Add typings to references in payload from `LanguageModelStreamResponseMessage`
|
119
|
+
- Add `original_index` to the base reference to reflect updated api
|
120
|
+
|
114
121
|
## [0.7.30] - 2025-06-20
|
115
122
|
- Adding litellm models `litellm:gemini-2-5-flash`, `gemini-2-5-flash-lite-preview-06-17`, `litellm:gemini-2-5-pro`, `litellm:gemini-2-5-pro-preview-06-05`
|
116
123
|
|
@@ -14,14 +14,14 @@ unique_toolkit/app/verification.py,sha256=GxFFwcJMy25fCA_Xe89wKW7bgqOu8PAs5y8QpH
|
|
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
16
|
unique_toolkit/chat/functions.py,sha256=QsJVhBXgK6jDWRYpEAt-22jy5NKGsYs4fmHrOEdHAyc,29865
|
17
|
-
unique_toolkit/chat/schemas.py,sha256=
|
17
|
+
unique_toolkit/chat/schemas.py,sha256=abPPeDtUIeEyKDnLhIqgIyqTsFANxh3j44EYrITBlHw,2786
|
18
18
|
unique_toolkit/chat/service.py,sha256=dRydaABJspU1KlFUQ_Q-rXl9lDkhgeh99SxAguY4s_M,37432
|
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
|
22
22
|
unique_toolkit/content/constants.py,sha256=1iy4Y67xobl5VTnJB6SxSyuoBWbdLl9244xfVMUZi5o,60
|
23
23
|
unique_toolkit/content/functions.py,sha256=0ELepm3_sl0SD_SYzvQVQ-jTdrcUqK5mVJZv0nQBuAw,18367
|
24
|
-
unique_toolkit/content/schemas.py,sha256=
|
24
|
+
unique_toolkit/content/schemas.py,sha256=KJ604BOx0vBh2AwlTCZkOo55aHsI6yj8vxDAARKKqEo,2995
|
25
25
|
unique_toolkit/content/service.py,sha256=jGRTIt0JQKL6qRyZ9-_njWJejKKvIvDOzEQrf8CdMaU,19491
|
26
26
|
unique_toolkit/content/utils.py,sha256=GUVPrkZfMoAj4MRoBs5BD_7vSuLZTZx69hyWzYFrI50,7747
|
27
27
|
unique_toolkit/embedding/__init__.py,sha256=uUyzjonPvuDCYsvXCIt7ErQXopLggpzX-MEQd3_e2kE,250
|
@@ -47,11 +47,11 @@ 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=WhgHbJgz4Z2aZt9TLdOpI0PGyYWA5R90tdwkwdDeT8c,11987
|
51
51
|
unique_toolkit/language_model/infos.py,sha256=w5__BVG-IiiEYKG1FwM838wzqNbYI3eCCEDocKezc0I,34801
|
52
52
|
unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO8pPIodzN4Q,3991
|
53
|
-
unique_toolkit/language_model/reference.py,sha256=
|
54
|
-
unique_toolkit/language_model/schemas.py,sha256=
|
53
|
+
unique_toolkit/language_model/reference.py,sha256=ntoWdJ_hly8FntTgg1qpj0ta55SOCCVsC5L49VqOiAQ,8067
|
54
|
+
unique_toolkit/language_model/schemas.py,sha256=AeuDRJFblGzEYcEMyrlxpOPk12Di3J45I9rT2xZrhEU,14332
|
55
55
|
unique_toolkit/language_model/service.py,sha256=VRkUk2XbijqGlnTTvqU7uCue6qtT7lpLd_Y8f3bWv1I,10486
|
56
56
|
unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
|
57
57
|
unique_toolkit/protocols/support.py,sha256=V15WEIFKVMyF1QCnR8vIi4GrJy4dfTCB6d6JlqPZ58o,2341
|
@@ -62,7 +62,7 @@ unique_toolkit/short_term_memory/schemas.py,sha256=OhfcXyF6ACdwIXW45sKzjtZX_gkcJ
|
|
62
62
|
unique_toolkit/short_term_memory/service.py,sha256=cqpXA0nMbi4PhFweg-Cql3u0RvaTi5c8Xjv0uHMiSGc,8112
|
63
63
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
64
64
|
unique_toolkit/smart_rules/compile.py,sha256=cxWjb2dxEI2HGsakKdVCkSNi7VK9mr08w5sDcFCQyWI,9553
|
65
|
-
unique_toolkit-0.7.
|
66
|
-
unique_toolkit-0.7.
|
67
|
-
unique_toolkit-0.7.
|
68
|
-
unique_toolkit-0.7.
|
65
|
+
unique_toolkit-0.7.32.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
66
|
+
unique_toolkit-0.7.32.dist-info/METADATA,sha256=qmPxpLockST_2FR2k05nfwgNDtI7C1pBK9fbNwCoKGE,24713
|
67
|
+
unique_toolkit-0.7.32.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
68
|
+
unique_toolkit-0.7.32.dist-info/RECORD,,
|
File without changes
|
File without changes
|