unique_toolkit 0.5.10__py3-none-any.whl → 0.5.12__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.
@@ -1,10 +1,10 @@
1
1
  import logging
2
2
  from typing import Optional
3
3
 
4
- from unique_toolkit.chat.state import ChatState
4
+ from unique_toolkit.app.schemas import Event
5
5
 
6
6
 
7
7
  class BaseService:
8
- def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
9
- self.state = state
8
+ def __init__(self, event: Event, logger: Optional[logging.Logger] = None):
9
+ self.event = event
10
10
  self.logger = logger or logging.getLogger(__name__)
@@ -0,0 +1,5 @@
1
+ from datetime import datetime
2
+
3
+
4
+ def get_datetime_now(format: str = "%Y-%m-%d %H:%M:%S.%f"):
5
+ return datetime.now().strftime(format)
@@ -0,0 +1,25 @@
1
+ from .init_logging import init_logging as init_logging
2
+ from .init_sdk import get_endpoint_secret as get_endpoint_secret
3
+ from .init_sdk import init_sdk as init_sdk
4
+ from .performance.async_tasks import (
5
+ run_async_tasks_parallel as run_async_tasks_parallel,
6
+ )
7
+ from .performance.async_wrapper import to_async as to_async
8
+ from .schemas import (
9
+ Event as Event,
10
+ )
11
+ from .schemas import (
12
+ EventAssistantMessage as EventAssistantMessage,
13
+ )
14
+ from .schemas import (
15
+ EventName as EventName,
16
+ )
17
+ from .schemas import (
18
+ EventPayload as EventPayload,
19
+ )
20
+ from .schemas import (
21
+ EventUserMessage as EventUserMessage,
22
+ )
23
+ from .verification import (
24
+ verify_signature_and_construct_event as verify_signature_and_construct_event,
25
+ )
@@ -1,12 +1,14 @@
1
1
  from enum import StrEnum
2
- from typing import Any
2
+ from typing import Any, Optional
3
3
 
4
4
  from humps import camelize
5
5
  from pydantic import BaseModel, ConfigDict
6
6
 
7
7
  # set config to convert camelCase to snake_case
8
8
  model_config = ConfigDict(
9
- alias_generator=camelize, populate_by_name=True, arbitrary_types_allowed=True
9
+ alias_generator=camelize,
10
+ populate_by_name=True,
11
+ arbitrary_types_allowed=True,
10
12
  )
11
13
 
12
14
 
@@ -19,7 +21,9 @@ class EventUserMessage(BaseModel):
19
21
 
20
22
  id: str
21
23
  text: str
24
+ original_text: str
22
25
  created_at: str
26
+ language: str
23
27
 
24
28
 
25
29
  class EventAssistantMessage(BaseModel):
@@ -29,6 +33,12 @@ class EventAssistantMessage(BaseModel):
29
33
  created_at: str
30
34
 
31
35
 
36
+ class EventAdditionalParameters(BaseModel):
37
+ model_config = model_config
38
+
39
+ translate_to_language: Optional[str] = None
40
+
41
+
32
42
  class EventPayload(BaseModel):
33
43
  model_config = model_config
34
44
 
@@ -39,7 +49,8 @@ class EventPayload(BaseModel):
39
49
  assistant_id: str
40
50
  user_message: EventUserMessage
41
51
  assistant_message: EventAssistantMessage
42
- text: str | None = None
52
+ text: Optional[str] = None
53
+ additional_parameters: Optional[EventAdditionalParameters] = None
43
54
 
44
55
 
45
56
  class Event(BaseModel):
@@ -50,5 +61,5 @@ class Event(BaseModel):
50
61
  user_id: str
51
62
  company_id: str
52
63
  payload: EventPayload
53
- created_at: int | None = None
54
- version: str | None = None
64
+ created_at: Optional[int] = None
65
+ version: Optional[str] = None
@@ -0,0 +1,6 @@
1
+ from .schemas import ChatMessage as ChatMessage
2
+ from .schemas import ChatMessageRole as ChatMessageRole
3
+ from .service import ChatService as ChatService
4
+ from .utils import (
5
+ convert_chat_history_to_injectable_string as convert_chat_history_to_injectable_string,
6
+ )
@@ -1,4 +1,4 @@
1
- from enum import Enum
1
+ from enum import StrEnum
2
2
 
3
3
  from humps import camelize
4
4
  from pydantic import BaseModel, ConfigDict, Field, field_validator
@@ -9,7 +9,7 @@ model_config = ConfigDict(
9
9
  )
10
10
 
11
11
 
12
- class ChatMessageRole(str, Enum):
12
+ class ChatMessageRole(StrEnum):
13
13
  USER = "user"
14
14
  ASSISTANT = "assistant"
15
15
 
@@ -5,9 +5,10 @@ from typing import Optional
5
5
  import unique_sdk
6
6
  from unique_sdk._list_object import ListObject
7
7
 
8
+ from unique_toolkit._common import _time_utils
8
9
  from unique_toolkit._common._base_service import BaseService
10
+ from unique_toolkit.app.schemas import Event
9
11
  from unique_toolkit.chat.schemas import ChatMessage, ChatMessageRole
10
- from unique_toolkit.chat.state import ChatState
11
12
  from unique_toolkit.content.schemas import ContentReference
12
13
  from unique_toolkit.content.utils import count_tokens
13
14
 
@@ -17,12 +18,12 @@ class ChatService(BaseService):
17
18
  Provides all functionalities to manage the chat session.
18
19
 
19
20
  Attributes:
20
- state (ChatState): The chat state.
21
+ event (Event): The Event object.
21
22
  logger (Optional[logging.Logger]): The logger. Defaults to None.
22
23
  """
23
24
 
24
- def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
25
- super().__init__(state, logger)
25
+ def __init__(self, event: Event, logger: Optional[logging.Logger] = None):
26
+ super().__init__(event, logger)
26
27
 
27
28
  DEFAULT_PERCENT_OF_MAX_TOKENS = 0.15
28
29
  DEFAULT_MAX_MESSAGES = 4
@@ -49,17 +50,18 @@ class ChatService(BaseService):
49
50
  Raises:
50
51
  Exception: If the modification fails.
51
52
  """
52
- message_id = message_id or self.state.assistant_message_id
53
+ message_id = message_id or self.event.payload.assistant_message.id
53
54
 
54
55
  try:
55
56
  message = unique_sdk.Message.modify(
56
- user_id=self.state.user_id,
57
- company_id=self.state.company_id,
58
- id=message_id, # type: ignore
59
- chatId=self.state.chat_id,
57
+ user_id=self.event.user_id,
58
+ company_id=self.event.company_id,
59
+ id=message_id,
60
+ chatId=self.event.payload.chat_id,
60
61
  text=content,
61
- references=self._map_references(references), # type: ignore
62
+ references=self._map_references(references),
62
63
  debugInfo=debug_info or {},
64
+ completedAt=_time_utils.get_datetime_now(), # type: ignore
63
65
  )
64
66
  except Exception as e:
65
67
  self.logger.error(f"Failed to modify assistant message: {e}")
@@ -88,17 +90,18 @@ class ChatService(BaseService):
88
90
  Raises:
89
91
  Exception: If the modification fails.
90
92
  """
91
- message_id = message_id or self.state.assistant_message_id
93
+ message_id = message_id or self.event.payload.assistant_message.id
92
94
 
93
95
  try:
94
96
  message = await unique_sdk.Message.modify_async(
95
- user_id=self.state.user_id,
96
- company_id=self.state.company_id,
97
- id=message_id, # type: ignore
98
- chatId=self.state.chat_id,
97
+ user_id=self.event.user_id,
98
+ company_id=self.event.company_id,
99
+ id=message_id,
100
+ chatId=self.event.payload.chat_id,
99
101
  text=content,
100
- references=self._map_references(references), # type: ignore
102
+ references=self._map_references(references),
101
103
  debugInfo=debug_info or {},
104
+ completedAt=_time_utils.get_datetime_now(), # type: ignore
102
105
  )
103
106
  except Exception as e:
104
107
  self.logger.error(f"Failed to modify assistant message: {e}")
@@ -210,10 +213,10 @@ class ChatService(BaseService):
210
213
 
211
214
  try:
212
215
  message = unique_sdk.Message.create(
213
- user_id=self.state.user_id,
214
- company_id=self.state.company_id,
215
- chatId=self.state.chat_id,
216
- assistantId=self.state.assistant_id,
216
+ user_id=self.event.user_id,
217
+ company_id=self.event.company_id,
218
+ chatId=self.event.payload.chat_id,
219
+ assistantId=self.event.payload.assistant_id,
217
220
  text=content,
218
221
  role=ChatMessageRole.ASSISTANT.name,
219
222
  references=self._map_references(references), # type: ignore
@@ -246,10 +249,10 @@ class ChatService(BaseService):
246
249
  """
247
250
  try:
248
251
  message = await unique_sdk.Message.create_async(
249
- user_id=self.state.user_id,
250
- company_id=self.state.company_id,
251
- chatId=self.state.chat_id,
252
- assistantId=self.state.assistant_id,
252
+ user_id=self.event.user_id,
253
+ company_id=self.event.company_id,
254
+ chatId=self.event.payload.chat_id,
255
+ assistantId=self.event.payload.assistant_id,
253
256
  text=content,
254
257
  role=ChatMessageRole.ASSISTANT.name,
255
258
  references=self._map_references(references), # type: ignore
@@ -274,13 +277,13 @@ class ChatService(BaseService):
274
277
  ]
275
278
 
276
279
  def _get_full_history(self):
277
- messages = self._trigger_list_messages(self.state.chat_id)
280
+ messages = self._trigger_list_messages(self.event.payload.chat_id)
278
281
  messages = self._filter_valid_messages(messages)
279
282
 
280
283
  return self._map_to_chat_messages(messages)
281
284
 
282
285
  async def _get_full_history_async(self):
283
- messages = await self._trigger_list_messages_async(self.state.chat_id)
286
+ messages = await self._trigger_list_messages_async(self.event.payload.chat_id)
284
287
  messages = self._filter_valid_messages(messages)
285
288
 
286
289
  return self._map_to_chat_messages(messages)
@@ -305,8 +308,8 @@ class ChatService(BaseService):
305
308
  def _trigger_list_messages(self, chat_id: str):
306
309
  try:
307
310
  messages = unique_sdk.Message.list(
308
- user_id=self.state.user_id,
309
- company_id=self.state.company_id,
311
+ user_id=self.event.user_id,
312
+ company_id=self.event.company_id,
310
313
  chatId=chat_id,
311
314
  )
312
315
  return messages
@@ -317,8 +320,8 @@ class ChatService(BaseService):
317
320
  async def _trigger_list_messages_async(self, chat_id: str):
318
321
  try:
319
322
  messages = await unique_sdk.Message.list_async(
320
- user_id=self.state.user_id,
321
- company_id=self.state.company_id,
323
+ user_id=self.event.user_id,
324
+ company_id=self.event.company_id,
322
325
  chatId=chat_id,
323
326
  )
324
327
  return messages
@@ -5,7 +5,7 @@ from unique_toolkit.app.schemas import Event
5
5
 
6
6
 
7
7
  @dataclass
8
- class ChatState:
8
+ class ChatStateTemplate:
9
9
  """
10
10
  Represents the state of the chat session.
11
11
 
@@ -36,12 +36,12 @@ class ChatState:
36
36
  event (Event): The Event object.
37
37
 
38
38
  Returns:
39
- ChatManager: The ChatManager instance.
39
+ ChatState: The ChatState instance.
40
40
  """
41
41
  return cls(
42
42
  user_id=event.user_id,
43
- chat_id=event.payload.chat_id,
44
43
  company_id=event.company_id,
44
+ chat_id=event.payload.chat_id,
45
45
  assistant_id=event.payload.assistant_id,
46
46
  user_message_text=event.payload.user_message.text,
47
47
  user_message_id=event.payload.user_message.id,
@@ -0,0 +1,37 @@
1
+ from .schemas import (
2
+ Content as Content,
3
+ )
4
+ from .schemas import (
5
+ ContentChunk as ContentChunk,
6
+ )
7
+ from .schemas import (
8
+ ContentMetadata as ContentMetadata,
9
+ )
10
+ from .schemas import (
11
+ ContentReference as ContentReference,
12
+ )
13
+ from .schemas import (
14
+ ContentRerankerConfig as ContentRerankerConfig,
15
+ )
16
+ from .schemas import (
17
+ ContentSearchResult as ContentSearchResult,
18
+ )
19
+ from .schemas import (
20
+ ContentSearchType as ContentSearchType,
21
+ )
22
+ from .schemas import (
23
+ ContentUploadInput as ContentUploadInput,
24
+ )
25
+ from .service import ContentService as ContentService
26
+ from .utils import (
27
+ count_tokens as count_tokens,
28
+ )
29
+ from .utils import (
30
+ merge_content_chunks as merge_content_chunks,
31
+ )
32
+ from .utils import (
33
+ pick_content_chunks_for_token_window as pick_content_chunks_for_token_window,
34
+ )
35
+ from .utils import (
36
+ sort_content_chunks as sort_content_chunks,
37
+ )
@@ -92,7 +92,7 @@ class ContentUploadInput(BaseModel):
92
92
  byte_size: Optional[int] = None
93
93
 
94
94
 
95
- class RerankerConfig(BaseModel):
95
+ class ContentRerankerConfig(BaseModel):
96
96
  model_config = model_config
97
97
  deployment_name: str = Field(serialization_alias="deploymentName")
98
98
  options: dict | None = None
@@ -8,13 +8,13 @@ import requests
8
8
  import unique_sdk
9
9
 
10
10
  from unique_toolkit._common._base_service import BaseService
11
- from unique_toolkit.chat.state import ChatState
11
+ from unique_toolkit.app.schemas import Event
12
12
  from unique_toolkit.content.schemas import (
13
13
  Content,
14
14
  ContentChunk,
15
+ ContentRerankerConfig,
15
16
  ContentSearchType,
16
17
  ContentUploadInput,
17
- RerankerConfig,
18
18
  )
19
19
 
20
20
 
@@ -23,12 +23,12 @@ class ContentService(BaseService):
23
23
  Provides methods for searching, downloading and uploading content in the knowledge base.
24
24
 
25
25
  Attributes:
26
- state (ChatState): The chat state.
26
+ event (Event): The Event object.
27
27
  logger (Optional[logging.Logger]): The logger. Defaults to None.
28
28
  """
29
29
 
30
- def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
31
- super().__init__(state, logger)
30
+ def __init__(self, event: Event, logger: Optional[logging.Logger] = None):
31
+ super().__init__(event, logger)
32
32
 
33
33
  DEFAULT_SEARCH_LANGUAGE = "english"
34
34
 
@@ -38,7 +38,7 @@ class ContentService(BaseService):
38
38
  search_type: ContentSearchType,
39
39
  limit: int,
40
40
  search_language: str = DEFAULT_SEARCH_LANGUAGE,
41
- reranker_config: Optional[RerankerConfig] = None,
41
+ reranker_config: Optional[ContentRerankerConfig] = None,
42
42
  scope_ids: Optional[list[str]] = None,
43
43
  chat_only: Optional[bool] = None,
44
44
  ) -> list[ContentChunk]:
@@ -50,7 +50,7 @@ class ContentService(BaseService):
50
50
  search_type (ContentSearchType): The type of search to perform.
51
51
  limit (int): The maximum number of results to return.
52
52
  search_language (str): The language for the full-text search. Defaults to "english".
53
- reranker_config (Optional[RerankerConfig]): The reranker configuration. Defaults to None.
53
+ reranker_config (Optional[ContentRerankerConfig]): The reranker configuration. Defaults to None.
54
54
  scope_ids (Optional[list[str]]): The scope IDs. Defaults to None.
55
55
  chat_only (Optional[bool]): Whether to search only in the current chat. Defaults to None.
56
56
 
@@ -62,9 +62,9 @@ class ContentService(BaseService):
62
62
 
63
63
  try:
64
64
  searches = unique_sdk.Search.create(
65
- user_id=self.state.user_id,
66
- company_id=self.state.company_id,
67
- chatId=self.state.chat_id,
65
+ user_id=self.event.user_id,
66
+ company_id=self.event.company_id,
67
+ chatId=self.event.payload.chat_id,
68
68
  searchString=search_string,
69
69
  searchType=search_type.name,
70
70
  scopeIds=scope_ids,
@@ -92,7 +92,7 @@ class ContentService(BaseService):
92
92
  search_type: ContentSearchType,
93
93
  limit: int,
94
94
  search_language: str = DEFAULT_SEARCH_LANGUAGE,
95
- reranker_config: Optional[RerankerConfig] = None,
95
+ reranker_config: Optional[ContentRerankerConfig] = None,
96
96
  scope_ids: Optional[list[str]] = None,
97
97
  chat_only: Optional[bool] = None,
98
98
  ):
@@ -104,7 +104,7 @@ class ContentService(BaseService):
104
104
  search_type (ContentSearchType): The type of search to perform.
105
105
  limit (int): The maximum number of results to return.
106
106
  search_language (str): The language for the full-text search. Defaults to "english".
107
- reranker_config (Optional[RerankerConfig]): The reranker configuration. Defaults to None.
107
+ reranker_config (Optional[ContentRerankerConfig]): The reranker configuration. Defaults to None.
108
108
  scope_ids (Optional[list[str]]): The scope IDs. Defaults to None.
109
109
  chat_only (Optional[bool]): Whether to search only in the current chat. Defaults to None.
110
110
 
@@ -116,9 +116,9 @@ class ContentService(BaseService):
116
116
 
117
117
  try:
118
118
  searches = await unique_sdk.Search.create_async(
119
- user_id=self.state.user_id,
120
- company_id=self.state.company_id,
121
- chatId=self.state.chat_id,
119
+ user_id=self.event.user_id,
120
+ company_id=self.event.company_id,
121
+ chatId=self.event.payload.chat_id,
122
122
  searchString=search_string,
123
123
  searchType=search_type.name,
124
124
  scopeIds=scope_ids,
@@ -156,9 +156,9 @@ class ContentService(BaseService):
156
156
  """
157
157
  try:
158
158
  contents = unique_sdk.Content.search(
159
- user_id=self.state.user_id,
160
- company_id=self.state.company_id,
161
- chatId=self.state.chat_id,
159
+ user_id=self.event.user_id,
160
+ company_id=self.event.company_id,
161
+ chatId=self.event.payload.chat_id,
162
162
  # TODO add type parameter
163
163
  where=where, # type: ignore
164
164
  )
@@ -183,9 +183,9 @@ class ContentService(BaseService):
183
183
  """
184
184
  try:
185
185
  contents = await unique_sdk.Content.search_async(
186
- user_id=self.state.user_id,
187
- company_id=self.state.company_id,
188
- chatId=self.state.chat_id,
186
+ user_id=self.event.user_id,
187
+ company_id=self.event.company_id,
188
+ chatId=self.event.payload.chat_id,
189
189
  # TODO add type parameter
190
190
  where=where, # type: ignore
191
191
  )
@@ -325,8 +325,8 @@ class ContentService(BaseService):
325
325
  "mimeType": input.mime_type,
326
326
  }
327
327
  content = unique_sdk.Content.upsert(
328
- user_id=self.state.user_id,
329
- company_id=self.state.company_id,
328
+ user_id=self.event.user_id,
329
+ company_id=self.event.company_id,
330
330
  input=input_json, # type: ignore
331
331
  fileUrl=content_url,
332
332
  scopeId=scope_id,
@@ -374,8 +374,8 @@ class ContentService(BaseService):
374
374
  headers = {
375
375
  "x-api-version": unique_sdk.api_version,
376
376
  "x-app-id": unique_sdk.app_id,
377
- "x-user-id": self.state.user_id,
378
- "x-company-id": self.state.company_id,
377
+ "x-user-id": self.event.user_id,
378
+ "x-company-id": self.event.company_id,
379
379
  "Authorization": "Bearer %s" % (unique_sdk.api_key,),
380
380
  }
381
381
 
@@ -122,7 +122,7 @@ def _generate_pages_postfix(chunks: list[ContentChunk]) -> str:
122
122
  return list(range(start, end + 1))
123
123
 
124
124
  page_numbers_array = [
125
- gen_all_numbers_in_between(s.start_page, s.end_page) for s in chunks
125
+ gen_all_numbers_in_between(c.start_page, c.end_page) for c in chunks
126
126
  ]
127
127
  page_numbers = [number for sublist in page_numbers_array for number in sublist]
128
128
  page_numbers = [p for p in page_numbers if p > 0]
@@ -171,7 +171,7 @@ def pick_content_chunks_for_token_window(
171
171
  return picked_chunks
172
172
 
173
173
 
174
- def count_tokens(text, encoding_model="cl100k_base") -> int:
174
+ def count_tokens(text: str, encoding_model="cl100k_base") -> int:
175
175
  """
176
176
  Counts the number of tokens in the provided text.
177
177
 
@@ -0,0 +1,5 @@
1
+ from .schemas import Embeddings as Embeddings
2
+ from .service import EmbeddingService as EmbeddingService
3
+ from .utils import (
4
+ calculate_cosine_similarity as calculate_cosine_similarity,
5
+ )
@@ -1,11 +1,10 @@
1
1
  import logging
2
2
  from typing import Optional
3
3
 
4
- import numpy as np
5
4
  import unique_sdk
6
5
 
7
6
  from unique_toolkit._common._base_service import BaseService
8
- from unique_toolkit.chat.state import ChatState
7
+ from unique_toolkit.app.schemas import Event
9
8
  from unique_toolkit.embedding.schemas import Embeddings
10
9
 
11
10
 
@@ -14,12 +13,12 @@ class EmbeddingService(BaseService):
14
13
  Provides methods to interact with the Embedding service.
15
14
 
16
15
  Attributes:
17
- state (ChatState): The ChatState object.
16
+ event (Event): The Event object.
18
17
  logger (Optional[logging.Logger]): The logger object. Defaults t∏o None.
19
18
  """
20
19
 
21
- def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
22
- super().__init__(state, logger)
20
+ def __init__(self, event: Event, logger: Optional[logging.Logger] = None):
21
+ super().__init__(event, logger)
23
22
 
24
23
  DEFAULT_TIMEOUT = 600_000
25
24
 
@@ -77,18 +76,8 @@ class EmbeddingService(BaseService):
77
76
 
78
77
  def _get_request_obj(self, texts: list[str], timeout: int) -> dict:
79
78
  return {
80
- "user_id": self.state.user_id,
81
- "company_id": self.state.company_id,
79
+ "user_id": self.event.user_id,
80
+ "company_id": self.event.company_id,
82
81
  "texts": texts,
83
82
  "timeout": timeout,
84
83
  }
85
-
86
- def get_cosine_similarity(
87
- self,
88
- embedding_1: list[float],
89
- embedding_2: list[float],
90
- ) -> float:
91
- """Get cosine similarity."""
92
- return np.dot(embedding_1, embedding_2) / (
93
- np.linalg.norm(embedding_1) * np.linalg.norm(embedding_2)
94
- )
@@ -0,0 +1,11 @@
1
+ import numpy as np
2
+
3
+
4
+ def calculate_cosine_similarity(
5
+ embedding_1: list[float],
6
+ embedding_2: list[float],
7
+ ) -> float:
8
+ """Get cosine similarity."""
9
+ return np.dot(embedding_1, embedding_2) / (
10
+ np.linalg.norm(embedding_1) * np.linalg.norm(embedding_2)
11
+ )
@@ -0,0 +1,59 @@
1
+ from .infos import LanguageModel as LanguageModel
2
+ from .infos import LanguageModelName as LanguageModelName
3
+ from .schemas import (
4
+ LanguageModelAssistantMessage as LanguageModelAssistantMessage,
5
+ )
6
+ from .schemas import (
7
+ LanguageModelCompletionChoice as LanguageModelCompletionChoice,
8
+ )
9
+ from .schemas import (
10
+ LanguageModelFunction as LanguageModelFunction,
11
+ )
12
+ from .schemas import (
13
+ LanguageModelFunctionCall as LanguageModelFunctionCall,
14
+ )
15
+ from .schemas import (
16
+ LanguageModelMessage as LanguageModelMessage,
17
+ )
18
+ from .schemas import (
19
+ LanguageModelMessageRole as LanguageModelMessageRole,
20
+ )
21
+ from .schemas import (
22
+ LanguageModelMessages as LanguageModelMessages,
23
+ )
24
+ from .schemas import (
25
+ LanguageModelResponse as LanguageModelResponse,
26
+ )
27
+ from .schemas import (
28
+ LanguageModelStreamResponse as LanguageModelStreamResponse,
29
+ )
30
+ from .schemas import (
31
+ LanguageModelStreamResponseMessage as LanguageModelStreamResponseMessage,
32
+ )
33
+ from .schemas import (
34
+ LanguageModelSystemMessage as LanguageModelSystemMessage,
35
+ )
36
+ from .schemas import (
37
+ LanguageModelTokenLimits as LanguageModelTokenLimits,
38
+ )
39
+ from .schemas import (
40
+ LanguageModelTool as LanguageModelTool,
41
+ )
42
+ from .schemas import (
43
+ LanguageModelToolParameterProperty as LanguageModelToolParameterProperty,
44
+ )
45
+ from .schemas import (
46
+ LanguageModelToolParameters as LanguageModelToolParameters,
47
+ )
48
+ from .schemas import (
49
+ LanguageModelUserMessage as LanguageModelUserMessage,
50
+ )
51
+ from .service import (
52
+ LanguageModelService as LanguageModelService,
53
+ )
54
+ from .utils import (
55
+ convert_string_to_json as convert_string_to_json,
56
+ )
57
+ from .utils import (
58
+ find_last_json_object as find_last_json_object,
59
+ )
@@ -1,4 +1,3 @@
1
- import warnings
2
1
  from datetime import date
3
2
  from enum import StrEnum
4
3
  from typing import ClassVar, Optional, Type, cast
@@ -149,10 +148,11 @@ class LanguageModel:
149
148
  def get_model_info(cls, model_name: LanguageModelName) -> LanguageModelInfo:
150
149
  for subclass in cls.__subclasses__():
151
150
  if hasattr(subclass, "info") and subclass._info.name == model_name:
152
- if subclass._info.retirement_at:
153
- warning_text = f"WARNING: {subclass._info.name} will be retired on {subclass._info.retirement_at.isoformat()} and from then on not accessible anymore. {subclass._info.retirement_text}"
154
- print(warning_text)
155
- warnings.warn(warning_text, DeprecationWarning, stacklevel=2)
151
+ # TODO find alternative solution for warning
152
+ # if subclass._info.retirement_at:
153
+ # warning_text = f"WARNING: {subclass._info.name} will be retired on {subclass._info.retirement_at.isoformat()} and from then on not accessible anymore. {subclass._info.retirement_text}"
154
+ # print(warning_text)
155
+ # warnings.warn(warning_text, DeprecationWarning, stacklevel=2)
156
156
  return subclass._info
157
157
  raise ValueError(f"Model {model_name} not found.")
158
158
 
@@ -24,7 +24,7 @@ class LanguageModelFunction(BaseModel):
24
24
 
25
25
  id: Optional[str] = None
26
26
  name: str
27
- arguments: Optional[dict[str, any]] = None # type: ignore
27
+ arguments: Optional[dict[str, list | dict | str | int | float | bool]] = None # type: ignore
28
28
 
29
29
  @field_validator("arguments", mode="before")
30
30
  def set_arguments(cls, value):
@@ -104,7 +104,7 @@ class LanguageModelStreamResponseMessage(BaseModel):
104
104
  role: LanguageModelMessageRole
105
105
  text: str
106
106
  original_text: Optional[str] = None
107
- references: list[dict[str, any]] = [] # type: ignore
107
+ references: list[dict[str, list | dict | str | int | float | bool]] = [] # type: ignore
108
108
 
109
109
  # TODO make sdk return role in lowercase
110
110
  # Currently needed as sdk returns role in uppercase
@@ -4,7 +4,7 @@ from typing import Optional, cast
4
4
  import unique_sdk
5
5
 
6
6
  from unique_toolkit._common._base_service import BaseService
7
- from unique_toolkit.chat.state import ChatState
7
+ from unique_toolkit.app.schemas import Event
8
8
  from unique_toolkit.content.schemas import ContentChunk
9
9
  from unique_toolkit.language_model.infos import LanguageModelName
10
10
  from unique_toolkit.language_model.schemas import (
@@ -20,12 +20,12 @@ class LanguageModelService(BaseService):
20
20
  Provides methods to interact with the Language Model by generating responses.
21
21
 
22
22
  Attributes:
23
- state (ChatState): The ChatState object.
23
+ event (Event): The Event object.
24
24
  logger (Optional[logging.Logger]): The logger object. Defaults to None.
25
25
  """
26
26
 
27
- def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
28
- super().__init__(state, logger)
27
+ def __init__(self, event: Event, logger: Optional[logging.Logger] = None):
28
+ super().__init__(event, logger)
29
29
 
30
30
  DEFAULT_COMPLETE_TIMEOUT = 240_000
31
31
  DEFAULT_COMPLETE_TEMPERATURE = 0.0
@@ -55,9 +55,9 @@ class LanguageModelService(BaseService):
55
55
  messages = messages.model_dump(exclude_none=True)
56
56
  try:
57
57
  response = unique_sdk.ChatCompletion.create(
58
- company_id=self.state.company_id,
58
+ company_id=self.event.company_id,
59
59
  # TODO change or extend types in unique_sdk
60
- model=model_name.name, # type: ignore
60
+ model=model_name.name,
61
61
  messages=cast(
62
62
  list[unique_sdk.Integrated.ChatCompletionRequestMessage],
63
63
  messages,
@@ -96,9 +96,9 @@ class LanguageModelService(BaseService):
96
96
  messages = messages.model_dump(exclude_none=True, exclude={"tool_calls"})
97
97
  try:
98
98
  response = await unique_sdk.ChatCompletion.create_async(
99
- company_id=self.state.company_id,
99
+ company_id=self.event.company_id,
100
100
  # TODO change or extend types in unique_sdk
101
- model=model_name.name, # type: ignore
101
+ model=model_name.name,
102
102
  messages=cast(
103
103
  list[unique_sdk.Integrated.ChatCompletionRequestMessage],
104
104
  messages,
@@ -145,21 +145,21 @@ class LanguageModelService(BaseService):
145
145
 
146
146
  try:
147
147
  response = unique_sdk.Integrated.chat_stream_completion(
148
- user_id=self.state.user_id,
149
- company_id=self.state.company_id,
150
- assistantMessageId=self.state.assistant_message_id, # type: ignore
151
- userMessageId=self.state.user_message_id, # type: ignore
148
+ user_id=self.event.user_id,
149
+ company_id=self.event.company_id,
150
+ assistantMessageId=self.event.payload.assistant_message.id,
151
+ userMessageId=self.event.payload.user_message.id,
152
152
  messages=cast(
153
153
  list[unique_sdk.Integrated.ChatCompletionRequestMessage],
154
154
  messages,
155
155
  ),
156
- chatId=self.state.chat_id,
156
+ chatId=self.event.payload.chat_id,
157
157
  searchContext=search_context,
158
158
  # TODO change or extend types in unique_sdk
159
- model=model_name.name, # type: ignore
159
+ model=model_name.name,
160
160
  timeout=timeout,
161
161
  temperature=temperature,
162
- assistantId=self.state.assistant_id,
162
+ assistantId=self.event.payload.assistant_id,
163
163
  debugInfo=debug_info,
164
164
  options=options, # type: ignore
165
165
  startText=start_text,
@@ -203,22 +203,22 @@ class LanguageModelService(BaseService):
203
203
 
204
204
  try:
205
205
  response = await unique_sdk.Integrated.chat_stream_completion_async(
206
- user_id=self.state.user_id,
207
- company_id=self.state.company_id,
208
- assistantMessageId=self.state.assistant_message_id, # type: ignore
209
- userMessageId=self.state.user_message_id, # type: ignore
206
+ user_id=self.event.user_id,
207
+ company_id=self.event.company_id,
208
+ assistantMessageId=self.event.payload.assistant_message.id,
209
+ userMessageId=self.event.payload.user_message.id,
210
210
  messages=cast(
211
211
  list[unique_sdk.Integrated.ChatCompletionRequestMessage],
212
212
  messages,
213
213
  ),
214
- chatId=self.state.chat_id,
214
+ chatId=self.event.payload.chat_id,
215
215
  searchContext=search_context,
216
- # TODO change or extend types in unique_sdk
217
- model=model_name.name, # type: ignore
216
+ model=model_name.name,
218
217
  timeout=timeout,
219
218
  temperature=temperature,
220
- assistantId=self.state.assistant_id,
219
+ assistantId=self.event.payload.assistant_id,
221
220
  debugInfo=debug_info,
221
+ # TODO change or extend types in unique_sdk
222
222
  options=options, # type: ignore
223
223
  startText=start_text,
224
224
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 0.5.10
3
+ Version: 0.5.12
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Martin Fadler
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.12
13
13
  Requires-Dist: numpy (>=1.26.4,<2.0.0)
14
14
  Requires-Dist: pydantic (>=2.8.2,<3.0.0)
15
15
  Requires-Dist: pyhumps (>=3.8.0,<4.0.0)
16
+ Requires-Dist: pytest-mock (>=3.14.0,<4.0.0)
16
17
  Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
17
18
  Requires-Dist: regex (>=2024.5.15,<2025.0.0)
18
19
  Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
@@ -55,7 +56,6 @@ The `unique_toolkit.app` module encompasses functions for initializing and secur
55
56
 
56
57
  The `unique_toolkit.chat` module encompasses all chat related functionality.
57
58
 
58
- - `state.py` comprises the ChatState which is used to store the current state of the chat interaction and the user information.
59
59
  - `service.py` comprises the ChatService and provides an interface to manage and load the chat history and interact with the chat ui, e.g., creating a new assistant message.
60
60
  - `schemas.py` comprises all relevant schemas, e.g., ChatMessage, used in the ChatService.
61
61
  - `utils.py` comprises utility functions to use and convert ChatMessage objects in assistants, e.g., convert_chat_history_to_injectable_string converts the chat history to a string that can be injected into a prompt.
@@ -101,6 +101,19 @@ All notable changes to this project will be documented in this file.
101
101
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
102
102
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
103
103
 
104
+ ## [0.5.12] - 2024-08-7
105
+ - added `completedAt` datetime to `unique_sdk.Message.modify` and `unique_sdk.Message.modify_async`
106
+ - added `original_text` and `language` to `EventUserMessage`
107
+
108
+ ## [0.5.11] - 2024-08-6
109
+ - made all domain specific functions and classes directly importable from `unique_toolkit.[DOMAIN_NAME]`
110
+ - renamed `RerankerConfig` to `ContentRerankerConfig`
111
+ - renamed `get_cosine_similarity` to `calculate_cosine_similarity` and moved it to `unique_toolkit.embedding.utils`
112
+ - moved `calculate_tokens` from `unique_toolkit.content.utils` to `unique_toolkit.embedding.utils`
113
+ - disabled deprecation warning in `LanguageModel`
114
+ - added `additional_parameters` to event
115
+ - removed `ChatState` and use `Event` instead
116
+
104
117
  ## [0.5.10] - 2024-08-6
105
118
  - fix content schema
106
119
 
@@ -0,0 +1,32 @@
1
+ unique_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ unique_toolkit/_common/_base_service.py,sha256=S8H0rAebx7GsOldA7xInLp3aQJt9yEPDQdsGSFRJsGg,276
3
+ unique_toolkit/_common/_time_utils.py,sha256=ztmTovTvr-3w71Ns2VwXC65OKUUh-sQlzbHdKTQWm-w,135
4
+ unique_toolkit/app/__init__.py,sha256=sZyGrz74jBlAjv6OcHgcp6VtP6-AKKpaVYjakr1Xk60,735
5
+ unique_toolkit/app/init_logging.py,sha256=Sh26SRxOj8i8dzobKhYha2lLrkrMTHfB1V4jR3h23gQ,678
6
+ unique_toolkit/app/init_sdk.py,sha256=Nv4Now4pMfM0AgRhbtatLpm_39rKxn0WmRLwmPhRl-8,1285
7
+ unique_toolkit/app/performance/async_tasks.py,sha256=H0l3OAcosLwNHZ8d2pd-Di4wHIXfclEvagi5kfqLFPA,1941
8
+ unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
9
+ unique_toolkit/app/schemas.py,sha256=_PIROOUtdKvZFZdvkCORhj-MVWvfkopIQW7VIFmguRg,1364
10
+ unique_toolkit/app/verification.py,sha256=UZqTHg3PX_QxMjeLH_BVBYoMVqMnMpeMoqvyTBKDqj8,1996
11
+ unique_toolkit/chat/__init__.py,sha256=1prdTVfLOf6NgU-Aa1VIO-XiR6OYuRm51LaVRfKDCqc,267
12
+ unique_toolkit/chat/schemas.py,sha256=ff4M-XMagF0Evn3FcKHHP5xzDEyufZgq9Dmit3i8r_E,802
13
+ unique_toolkit/chat/service.py,sha256=mjzj0GCpIbGMX_k1aei8BY-132DCPv53FI7TqbXfaKk,13544
14
+ unique_toolkit/chat/state.py,sha256=Cjgwv_2vhDFbV69xxsn7SefhaoIAEqLx3ferdVFCnOg,1445
15
+ unique_toolkit/chat/utils.py,sha256=ihm-wQykBWhB4liR3LnwPVPt_qGW6ETq21Mw4HY0THE,854
16
+ unique_toolkit/content/__init__.py,sha256=MSH2sxjQyKD2Sef92fzE5Dt9SihdzivB6yliSwJfTmQ,890
17
+ unique_toolkit/content/schemas.py,sha256=UlC5nBIaFkq9TD31LR6ioG9JRZ1ScmtABi0l06HZR70,2231
18
+ unique_toolkit/content/service.py,sha256=4CHqZDE3C-VQpG6RAlenarvBmBgI28Ec6T9HZf9TB84,13565
19
+ unique_toolkit/content/utils.py,sha256=Lake671plRsqNvO3pN_rmyVcpwbdED_KQpLcCnc4lv4,6902
20
+ unique_toolkit/embedding/__init__.py,sha256=dr8M9jvslQTxPpxgaGwzxY0FildiWf-DidN_cahPAWw,191
21
+ unique_toolkit/embedding/schemas.py,sha256=1GvKCaSk4jixzVQ2PKq8yDqwGEVY_hWclYtoAr6CC2g,96
22
+ unique_toolkit/embedding/service.py,sha256=Iiw-sbdkjuWlWMfLM9qyC4GNTJOotQAaVjkYvh5Su4Y,2370
23
+ unique_toolkit/embedding/utils.py,sha256=v86lo__bCJbxZBQ3OcLu5SuwT6NbFfWlcq8iyk6BuzQ,279
24
+ unique_toolkit/language_model/__init__.py,sha256=QgU_uwpVh1URQyVs6l-6Am4UwmEEhuGXNic3dUZ0FCc,1701
25
+ unique_toolkit/language_model/infos.py,sha256=W74PiBkAIEdTdgygdVoq_EWlziVOOfhSuETq4dKX7LM,8934
26
+ unique_toolkit/language_model/schemas.py,sha256=6PySftHNX1e00ncieRn4h35T4VneOO8j-mfpkC8Cvk8,4447
27
+ unique_toolkit/language_model/service.py,sha256=JjsOOcGDcR7db3yF3_oDXclEGfxqmwWpL5jor7Q42cU,10470
28
+ unique_toolkit/language_model/utils.py,sha256=WBPj1XKkDgxy_-T8HCZvsfkkSzj_1w4UZzNmyvdbBLY,1081
29
+ unique_toolkit-0.5.12.dist-info/LICENSE,sha256=bIeCWCYuoUU_MzNdg48-ubJSVm7qxakaRbzTiJ5uxrs,1065
30
+ unique_toolkit-0.5.12.dist-info/METADATA,sha256=ttyZ2AUYRAvvYkaV_B8_UC3TVER9tdHQXI2rXgrhXBQ,9812
31
+ unique_toolkit-0.5.12.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
32
+ unique_toolkit-0.5.12.dist-info/RECORD,,
@@ -1,25 +0,0 @@
1
- unique_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- unique_toolkit/_common/_base_service.py,sha256=SDhO69RA6E1ydUuV9N99RKreHZbQmMJj6SCdrYiakhU,283
3
- unique_toolkit/app/init_logging.py,sha256=Sh26SRxOj8i8dzobKhYha2lLrkrMTHfB1V4jR3h23gQ,678
4
- unique_toolkit/app/init_sdk.py,sha256=Nv4Now4pMfM0AgRhbtatLpm_39rKxn0WmRLwmPhRl-8,1285
5
- unique_toolkit/app/performance/async_tasks.py,sha256=H0l3OAcosLwNHZ8d2pd-Di4wHIXfclEvagi5kfqLFPA,1941
6
- unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
7
- unique_toolkit/app/schemas.py,sha256=UAbIkrgdqwWEwKqnJwB4TNQWuJgEsFzDxqJbEC8xcOc,1098
8
- unique_toolkit/app/verification.py,sha256=UZqTHg3PX_QxMjeLH_BVBYoMVqMnMpeMoqvyTBKDqj8,1996
9
- unique_toolkit/chat/schemas.py,sha256=TYqrDy96ynP7XpnT_abOJlq6LkqBTdKwEft4YHeEgR8,801
10
- unique_toolkit/chat/service.py,sha256=jTxFchdjcGp3IQZxWR4x3XTdATxodP0xD4LGJZYltVw,13338
11
- unique_toolkit/chat/state.py,sha256=qrXkxmYlTM6PRpHX6j_vhJNWkJX4r-xgJ3NvqM80rAY,1441
12
- unique_toolkit/chat/utils.py,sha256=ihm-wQykBWhB4liR3LnwPVPt_qGW6ETq21Mw4HY0THE,854
13
- unique_toolkit/content/schemas.py,sha256=5Tkn6fulop6Ya2iCZvth7I5XPwi8QPqPUgDFV7ZAQQg,2224
14
- unique_toolkit/content/service.py,sha256=_o2mCgi0cN3YIvlFFJnwBZw8YHzR37DM2Mqsk157IRc,13507
15
- unique_toolkit/content/utils.py,sha256=x3ABo8ZCRm3YJAQwDtrr82z77DmW4Mei7KCIITjP0fk,6897
16
- unique_toolkit/embedding/schemas.py,sha256=1GvKCaSk4jixzVQ2PKq8yDqwGEVY_hWclYtoAr6CC2g,96
17
- unique_toolkit/embedding/service.py,sha256=xcU84ANMIebBui_AWBhfN1rqz7evXYRgg_Z-132veNE,2703
18
- unique_toolkit/language_model/infos.py,sha256=NhAkeW7PyusSIHCMvwRikLlzGG4tOXSLf_Fnq7V9rNE,8881
19
- unique_toolkit/language_model/schemas.py,sha256=kTGSGT3ygrH3guQELOWpxN4MTgEPuudi-CTvRu-zCcI,4377
20
- unique_toolkit/language_model/service.py,sha256=0g0nAGj9Te16YHFhqO9pkszhEwtuZ6bSqor6hi49e6c,10549
21
- unique_toolkit/language_model/utils.py,sha256=WBPj1XKkDgxy_-T8HCZvsfkkSzj_1w4UZzNmyvdbBLY,1081
22
- unique_toolkit-0.5.10.dist-info/LICENSE,sha256=bIeCWCYuoUU_MzNdg48-ubJSVm7qxakaRbzTiJ5uxrs,1065
23
- unique_toolkit-0.5.10.dist-info/METADATA,sha256=wZsvcVpS4cZhkXfa9PRrycLHMoOnKW0c8tDK6V0FY5Y,9173
24
- unique_toolkit-0.5.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
25
- unique_toolkit-0.5.10.dist-info/RECORD,,