unique_toolkit 0.7.30__tar.gz → 0.7.32__tar.gz

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 (69) hide show
  1. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/CHANGELOG.md +7 -0
  2. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/PKG-INFO +9 -2
  3. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/pyproject.toml +2 -2
  4. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/schemas.py +3 -10
  5. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/content/schemas.py +12 -2
  6. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/functions.py +5 -15
  7. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/reference.py +14 -28
  8. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/schemas.py +36 -1
  9. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/LICENSE +0 -0
  10. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/README.md +0 -0
  11. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/__init__.py +0 -0
  12. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/_common/_base_service.py +0 -0
  13. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/_common/_time_utils.py +0 -0
  14. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/_common/exception.py +0 -0
  15. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/_common/validate_required_values.py +0 -0
  16. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/_common/validators.py +0 -0
  17. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/__init__.py +0 -0
  18. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/init_logging.py +0 -0
  19. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/init_sdk.py +0 -0
  20. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/performance/async_tasks.py +0 -0
  21. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/performance/async_wrapper.py +0 -0
  22. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/schemas.py +0 -0
  23. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/app/verification.py +0 -0
  24. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/__init__.py +0 -0
  25. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/constants.py +0 -0
  26. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/functions.py +0 -0
  27. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/service.py +0 -0
  28. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/state.py +0 -0
  29. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/chat/utils.py +0 -0
  30. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/content/__init__.py +0 -0
  31. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/content/constants.py +0 -0
  32. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/content/functions.py +0 -0
  33. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/content/service.py +0 -0
  34. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/content/utils.py +0 -0
  35. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/embedding/__init__.py +0 -0
  36. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/embedding/constants.py +0 -0
  37. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/embedding/functions.py +0 -0
  38. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/embedding/schemas.py +0 -0
  39. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/embedding/service.py +0 -0
  40. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/embedding/utils.py +0 -0
  41. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/__init__.py +0 -0
  42. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/config.py +0 -0
  43. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/constants.py +0 -0
  44. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/context_relevancy/constants.py +0 -0
  45. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/context_relevancy/prompts.py +0 -0
  46. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/context_relevancy/service.py +0 -0
  47. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/context_relevancy/utils.py +0 -0
  48. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/exception.py +0 -0
  49. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/hallucination/constants.py +0 -0
  50. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/hallucination/prompts.py +0 -0
  51. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/hallucination/service.py +0 -0
  52. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/hallucination/utils.py +0 -0
  53. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/output_parser.py +0 -0
  54. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/evaluators/schemas.py +0 -0
  55. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/__init__.py +0 -0
  56. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/builder.py +0 -0
  57. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/constants.py +0 -0
  58. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/infos.py +0 -0
  59. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/prompt.py +0 -0
  60. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/service.py +0 -0
  61. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/language_model/utils.py +0 -0
  62. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/protocols/support.py +0 -0
  63. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/short_term_memory/__init__.py +0 -0
  64. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/short_term_memory/constants.py +0 -0
  65. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/short_term_memory/functions.py +0 -0
  66. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/short_term_memory/schemas.py +0 -0
  67. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/short_term_memory/service.py +0 -0
  68. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/smart_rules/__init__.py +0 -0
  69. {unique_toolkit-0.7.30 → unique_toolkit-0.7.32}/unique_toolkit/smart_rules/compile.py +0 -0
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.7.32] - 2025-06-24
9
+ - Create `classmethod` for `LanguageModelMessages` to load raw messages to root
10
+
11
+ ## [0.7.31] - 2025-06-19
12
+ - Add typings to references in payload from `LanguageModelStreamResponseMessage`
13
+ - Add `original_index` to the base reference to reflect updated api
14
+
8
15
  ## [0.7.30] - 2025-06-20
9
16
  - 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`
10
17
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 0.7.30
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.33,<0.10.0)
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
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_toolkit"
3
- version = "0.7.30"
3
+ version = "0.7.32"
4
4
  description = ""
5
5
  authors = [
6
6
  "Martin Fadler <martin.fadler@unique.ch>",
@@ -20,7 +20,7 @@ numpy = "^1.26.4"
20
20
  python-dotenv = "^1.0.1"
21
21
  regex = "^2024.5.15"
22
22
  tiktoken = "^0.7.0"
23
- unique-sdk = "^0.9.33"
23
+ unique-sdk = "^0.9.36"
24
24
 
25
25
  [tool.poetry.group.dev.dependencies]
26
26
  ruff = "0.11.7"
@@ -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[Reference] | None = None
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
- message_id: str
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=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=[u.model_dump() for u in message.references or []],
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 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
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[PotentialReference],
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 = [Reference(**ref.model_dump()) for ref in ref_found]
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[PotentialReference],
36
+ search_context: list[ContentChunk],
52
37
  message_id: str,
53
38
  model: str | None = None,
54
- ) -> tuple[str, list[NodeReference]]:
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, bool]: (processed_text, ref_found)
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[PotentialReference],
157
+ search_context: list[ContentChunk],
173
158
  message_id: str,
174
- ) -> list[NodeReference]:
159
+ ) -> list[ContentReference]:
175
160
  """Find references in text based on search context."""
176
- references: list[NodeReference] = []
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
- NodeReference(
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[NodeReference]) -> str:
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[dict[str, list | dict | str | int | float | bool]] = [] # type: ignore
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
 
File without changes