unique_toolkit 0.7.30__py3-none-any.whl → 0.7.31__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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 0.7.30
3
+ Version: 0.7.31
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Martin Fadler
@@ -111,6 +111,10 @@ 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.31] - 2025-06-19
115
+ - Add typings to references in payload from `LanguageModelStreamResponseMessage`
116
+ - Add `original_index` to the base reference to reflect updated api
117
+
114
118
  ## [0.7.30] - 2025-06-20
115
119
  - 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
120
 
@@ -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=ct3BbvdQmpcNeDmJdc-Iz33LX1_3O-SGVgrsuT0B99k,2881
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=iednldGojmoy9iPZwuIW23BfhWLE9G-fG_qAhxSgr7k,2451
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=J54mzKs-uOBejpiMDa1YviKvJDcYl0gvEF1CfLb7_S4,12208
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=TrRfnxd-cjpdijmZ1dKII87aEACIbW7iU_cE9gtGuH4,8314
54
- unique_toolkit/language_model/schemas.py,sha256=DJD2aoMfs2Irnc4rzOrVuV4Fbt84LQAiDGG5rse1dgk,12770
53
+ unique_toolkit/language_model/reference.py,sha256=ntoWdJ_hly8FntTgg1qpj0ta55SOCCVsC5L49VqOiAQ,8067
54
+ unique_toolkit/language_model/schemas.py,sha256=_fJ9rckKaS082wd2x9DrJ9N6B7iTJ9ytFnq4eIFDNAQ,12781
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.30.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
66
- unique_toolkit-0.7.30.dist-info/METADATA,sha256=GC9KCCAiwU1l1IvyhGM-U9qqRsW_9I47tdNSVGhu5dE,24431
67
- unique_toolkit-0.7.30.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
68
- unique_toolkit-0.7.30.dist-info/RECORD,,
65
+ unique_toolkit-0.7.31.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
66
+ unique_toolkit-0.7.31.dist-info/METADATA,sha256=aNS24gdydQe6icQg_M3EFprEMJ2o8qcR-95-lya8tj8,24607
67
+ unique_toolkit-0.7.31.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
68
+ unique_toolkit-0.7.31.dist-info/RECORD,,