unique_toolkit 0.0.1__py3-none-any.whl → 0.5.0__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/__init__.py +0 -3
- unique_toolkit/{observability/log_config.py → app/init_logging.py} +10 -10
- unique_toolkit/app/init_sdk.py +41 -0
- unique_toolkit/{performance → app/performance}/async_executor.py +44 -17
- unique_toolkit/app/performance/async_wrapper.py +28 -0
- unique_toolkit/{event/schema.py → app/schemas.py} +17 -10
- unique_toolkit/app/verification.py +58 -0
- unique_toolkit/chat/schemas.py +30 -0
- unique_toolkit/chat/service.py +285 -87
- unique_toolkit/chat/state.py +22 -10
- unique_toolkit/chat/utils.py +25 -0
- unique_toolkit/content/schemas.py +90 -0
- unique_toolkit/content/service.py +356 -0
- unique_toolkit/content/utils.py +188 -0
- unique_toolkit/embedding/schemas.py +5 -0
- unique_toolkit/embedding/service.py +89 -0
- unique_toolkit/language_model/infos.py +305 -0
- unique_toolkit/language_model/schemas.py +168 -0
- unique_toolkit/language_model/service.py +261 -0
- unique_toolkit/language_model/utils.py +44 -0
- {unique_toolkit-0.0.1.dist-info → unique_toolkit-0.5.0.dist-info}/LICENSE +1 -1
- unique_toolkit-0.5.0.dist-info/METADATA +135 -0
- unique_toolkit-0.5.0.dist-info/RECORD +24 -0
- unique_toolkit/chat/__init__.py +0 -3
- unique_toolkit/chat/messages.py +0 -24
- unique_toolkit/event/__init__.py +0 -1
- unique_toolkit/event/constants.py +0 -1
- unique_toolkit/llm/__init__.py +0 -2
- unique_toolkit/llm/json_parser.py +0 -21
- unique_toolkit/llm/models.py +0 -37
- unique_toolkit/llm/service.py +0 -163
- unique_toolkit/performance/__init__.py +0 -1
- unique_toolkit/performance/async_wrapper.py +0 -13
- unique_toolkit/sdk/init.py +0 -19
- unique_toolkit/search/service.py +0 -118
- unique_toolkit/security/verify.py +0 -29
- unique_toolkit-0.0.1.dist-info/METADATA +0 -33
- unique_toolkit-0.0.1.dist-info/RECORD +0 -23
- {unique_toolkit-0.0.1.dist-info → unique_toolkit-0.5.0.dist-info}/WHEEL +0 -0
unique_toolkit/chat/service.py
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
-
import
|
2
|
-
|
1
|
+
import logging
|
2
|
+
import re
|
3
|
+
from typing import Optional
|
3
4
|
|
4
|
-
|
5
|
+
import unique_sdk
|
5
6
|
|
6
|
-
from .
|
7
|
+
from unique_toolkit.app.performance.async_wrapper import async_warning, to_async
|
8
|
+
from unique_toolkit.chat.schemas import ChatMessage, ChatMessageRole
|
9
|
+
from unique_toolkit.chat.state import ChatState
|
10
|
+
from unique_toolkit.content.schemas import ContentReference
|
11
|
+
from unique_toolkit.content.utils import count_tokens
|
7
12
|
|
8
13
|
|
9
14
|
class ChatService:
|
@@ -12,171 +17,364 @@ class ChatService:
|
|
12
17
|
|
13
18
|
Attributes:
|
14
19
|
state (ChatState): The chat state.
|
20
|
+
logger (Optional[logging.Logger]): The logger. Defaults to None.
|
15
21
|
"""
|
16
22
|
|
17
|
-
def __init__(self, state: ChatState):
|
23
|
+
def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
|
18
24
|
self.state = state
|
25
|
+
self.logger = logger or logging.getLogger(__name__)
|
19
26
|
|
20
27
|
def modify_assistant_message(
|
21
28
|
self,
|
22
|
-
|
23
|
-
|
24
|
-
references: list = [],
|
29
|
+
content: str,
|
30
|
+
references: list[ContentReference] = [],
|
25
31
|
debug_info: dict = {},
|
26
|
-
|
32
|
+
message_id: Optional[str] = None,
|
33
|
+
) -> ChatMessage:
|
27
34
|
"""
|
28
35
|
Modifies a message in the chat session synchronously.
|
29
36
|
|
30
37
|
Args:
|
31
|
-
|
32
|
-
references (
|
33
|
-
debug_info (
|
38
|
+
content (str): The new content for the message.
|
39
|
+
references (list[ContentReference]): list of ContentReference objects. Defaults to [].
|
40
|
+
debug_info (dict[str, Any]]]): Debug information. Defaults to {}.
|
41
|
+
message_id (Optional[str]): The message ID. Defaults to None.
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
ChatMessage: The modified message.
|
45
|
+
|
46
|
+
Raises:
|
47
|
+
Exception: If the modification fails.
|
34
48
|
"""
|
35
|
-
self._trigger_modify_assistant_message(
|
49
|
+
return self._trigger_modify_assistant_message(
|
50
|
+
content=content,
|
51
|
+
message_id=message_id,
|
52
|
+
references=references,
|
53
|
+
debug_info=debug_info,
|
54
|
+
)
|
36
55
|
|
37
56
|
@to_async
|
57
|
+
@async_warning
|
38
58
|
def async_modify_assistant_message(
|
39
59
|
self,
|
40
|
-
|
41
|
-
|
42
|
-
references: list = [],
|
60
|
+
content: str,
|
61
|
+
references: list[ContentReference] = [],
|
43
62
|
debug_info: dict = {},
|
44
|
-
|
63
|
+
message_id: Optional[str] = None,
|
64
|
+
) -> ChatMessage:
|
45
65
|
"""
|
46
66
|
Modifies a message in the chat session asynchronously.
|
47
67
|
|
48
68
|
Args:
|
49
|
-
|
50
|
-
|
69
|
+
content (str): The new content for the message.
|
70
|
+
message_id (str, optional): The message ID. Defaults to None, then the ChatState assistant message id is used.
|
71
|
+
references (list[ContentReference]): list of ContentReference objects. Defaults to None.
|
51
72
|
debug_info (Optional[dict[str, Any]]], optional): Debug information. Defaults to None.
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
ChatMessage: The modified message.
|
76
|
+
|
77
|
+
Raises:
|
78
|
+
Exception: If the modification fails.
|
79
|
+
"""
|
80
|
+
return self._trigger_modify_assistant_message(
|
81
|
+
content,
|
82
|
+
message_id,
|
83
|
+
references,
|
84
|
+
debug_info,
|
85
|
+
)
|
86
|
+
|
87
|
+
def get_full_history(self) -> list[ChatMessage]:
|
88
|
+
"""
|
89
|
+
Loads the full chat history for the chat session synchronously.
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
list[ChatMessage]: The full chat history.
|
93
|
+
|
94
|
+
Raises:
|
95
|
+
Exception: If the loading fails.
|
52
96
|
"""
|
53
|
-
self.
|
97
|
+
return self._get_full_history()
|
54
98
|
|
55
|
-
|
99
|
+
@to_async
|
100
|
+
@async_warning
|
101
|
+
def async_get_full_history(self) -> list[ChatMessage]:
|
102
|
+
"""
|
103
|
+
Loads the full chat history for the chat session asynchronously.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
list[ChatMessage]: The full chat history.
|
107
|
+
|
108
|
+
Raises:
|
109
|
+
Exception: If the loading fails.
|
110
|
+
"""
|
111
|
+
return self._get_full_history()
|
112
|
+
|
113
|
+
def get_full_and_selected_history(
|
56
114
|
self,
|
57
|
-
|
58
|
-
max_tokens: int,
|
115
|
+
token_limit: int,
|
59
116
|
percent_of_max_tokens: float,
|
60
117
|
max_messages: int,
|
61
|
-
):
|
118
|
+
) -> tuple[list[ChatMessage], list[ChatMessage]]:
|
62
119
|
"""
|
63
120
|
Loads the chat history for the chat session synchronously.
|
64
121
|
|
65
122
|
Args:
|
66
|
-
|
123
|
+
token_limit (int): The maximum number of tokens to load.
|
67
124
|
percent_of_max_tokens (float): The percentage of the maximum tokens to load.
|
68
125
|
max_messages (int): The maximum number of messages to load.
|
69
126
|
|
70
127
|
Returns:
|
71
|
-
list[
|
128
|
+
tuple[list[ChatMessage], list[ChatMessage]]: The selected and full chat history.
|
129
|
+
|
130
|
+
Raises:
|
131
|
+
Exception: If the loading fails.
|
72
132
|
"""
|
73
|
-
return self.
|
74
|
-
|
133
|
+
return self._get_full_and_selected_history(
|
134
|
+
token_limit=token_limit,
|
135
|
+
percent_of_max_tokens=percent_of_max_tokens,
|
136
|
+
max_messages=max_messages,
|
75
137
|
)
|
76
138
|
|
77
139
|
@to_async
|
78
|
-
|
140
|
+
@async_warning
|
141
|
+
def async_get_full_and_selected_history(
|
79
142
|
self,
|
80
|
-
|
81
|
-
max_tokens: int,
|
143
|
+
token_limit: int,
|
82
144
|
percent_of_max_tokens: float,
|
83
145
|
max_messages: int,
|
84
|
-
):
|
146
|
+
) -> tuple[list[ChatMessage], list[ChatMessage]]:
|
85
147
|
"""
|
86
148
|
Loads the chat history for the chat session asynchronously.
|
87
149
|
|
88
150
|
Args:
|
89
|
-
|
151
|
+
token_limit (int): The maximum number of tokens to load.
|
90
152
|
percent_of_max_tokens (float): The percentage of the maximum tokens to load.
|
91
153
|
max_messages (int): The maximum number of messages to load.
|
92
154
|
|
93
155
|
Returns:
|
94
|
-
list[
|
156
|
+
tuple[list[ChatMessage], list[ChatMessage]]: The selected and full chat history.
|
157
|
+
|
158
|
+
Raises:
|
159
|
+
Exception: If the loading fails.
|
95
160
|
"""
|
96
|
-
return self.
|
97
|
-
|
161
|
+
return self._get_full_and_selected_history(
|
162
|
+
token_limit=token_limit,
|
163
|
+
percent_of_max_tokens=percent_of_max_tokens,
|
164
|
+
max_messages=max_messages,
|
98
165
|
)
|
99
166
|
|
100
167
|
def create_assistant_message(
|
101
168
|
self,
|
102
|
-
|
103
|
-
|
104
|
-
references: list = [],
|
169
|
+
content: str,
|
170
|
+
references: list[ContentReference] = [],
|
105
171
|
debug_info: dict = {},
|
106
172
|
):
|
107
173
|
"""
|
108
174
|
Creates a message in the chat session synchronously.
|
109
175
|
|
110
176
|
Args:
|
111
|
-
|
112
|
-
references (
|
113
|
-
debug_info (
|
177
|
+
content (str): The content for the message.
|
178
|
+
references (list[ContentReference]): list of ContentReference objects. Defaults to None.
|
179
|
+
debug_info (dict[str, Any]]): Debug information. Defaults to None.
|
180
|
+
|
181
|
+
Returns:
|
182
|
+
ChatMessage: The created message.
|
183
|
+
|
184
|
+
Raises:
|
185
|
+
Exception: If the creation fails.
|
114
186
|
"""
|
115
|
-
return self._trigger_create_assistant_message(
|
187
|
+
return self._trigger_create_assistant_message(
|
188
|
+
content=content,
|
189
|
+
references=references,
|
190
|
+
debug_info=debug_info,
|
191
|
+
)
|
116
192
|
|
117
193
|
@to_async
|
194
|
+
@async_warning
|
118
195
|
def async_create_assistant_message(
|
119
196
|
self,
|
120
|
-
|
121
|
-
|
122
|
-
references: list = [],
|
197
|
+
content: str,
|
198
|
+
references: list[ContentReference] = [],
|
123
199
|
debug_info: dict = {},
|
124
200
|
):
|
125
201
|
"""
|
126
202
|
Creates a message in the chat session asynchronously.
|
127
203
|
|
128
204
|
Args:
|
129
|
-
|
130
|
-
references (
|
131
|
-
debug_info (
|
205
|
+
content (str): The content for the message.
|
206
|
+
references (list[ContentReference]): list of references. Defaults to None.
|
207
|
+
debug_info (dict[str, Any]]): Debug information. Defaults to None.
|
208
|
+
|
209
|
+
Returns:
|
210
|
+
ChatMessage: The created message.
|
211
|
+
|
212
|
+
Raises:
|
213
|
+
Exception: If the creation fails.
|
132
214
|
"""
|
133
|
-
|
215
|
+
|
216
|
+
return self._trigger_create_assistant_message(
|
217
|
+
content=content,
|
218
|
+
references=references,
|
219
|
+
debug_info=debug_info,
|
220
|
+
)
|
134
221
|
|
135
222
|
def _trigger_modify_assistant_message(
|
136
223
|
self,
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
224
|
+
content: str,
|
225
|
+
message_id: Optional[str],
|
226
|
+
references: list[ContentReference],
|
227
|
+
debug_info: dict,
|
228
|
+
) -> ChatMessage:
|
229
|
+
message_id = message_id or self.state.assistant_message_id
|
230
|
+
|
231
|
+
try:
|
232
|
+
message = unique_sdk.Message.modify(
|
233
|
+
user_id=self.state.user_id,
|
234
|
+
company_id=self.state.company_id,
|
235
|
+
id=message_id, # type: ignore
|
236
|
+
chatId=self.state.chat_id,
|
237
|
+
text=content,
|
238
|
+
references=self._map_references(references), # type: ignore
|
239
|
+
debugInfo=debug_info or {},
|
240
|
+
)
|
241
|
+
except Exception as e:
|
242
|
+
self.logger.error(f"Failed to modify assistant message: {e}")
|
243
|
+
raise e
|
244
|
+
return ChatMessage(**message)
|
150
245
|
|
151
|
-
def
|
246
|
+
def _trigger_create_assistant_message(
|
152
247
|
self,
|
153
|
-
|
154
|
-
|
155
|
-
|
248
|
+
content: str,
|
249
|
+
references: list[ContentReference],
|
250
|
+
debug_info: dict,
|
251
|
+
) -> ChatMessage:
|
252
|
+
try:
|
253
|
+
message = unique_sdk.Message.create(
|
254
|
+
user_id=self.state.user_id,
|
255
|
+
company_id=self.state.company_id,
|
256
|
+
chatId=self.state.chat_id,
|
257
|
+
assistantId=self.state.assistant_id,
|
258
|
+
text=content,
|
259
|
+
role=ChatMessageRole.ASSISTANT.name,
|
260
|
+
references=self._map_references(references), # type: ignore
|
261
|
+
debugInfo=debug_info,
|
262
|
+
)
|
263
|
+
except Exception as e:
|
264
|
+
self.logger.error(f"Failed to create assistant message: {e}")
|
265
|
+
raise e
|
266
|
+
return ChatMessage(**message)
|
267
|
+
|
268
|
+
@staticmethod
|
269
|
+
def _map_references(references: list[ContentReference]):
|
270
|
+
return [
|
271
|
+
{
|
272
|
+
"name": ref.name,
|
273
|
+
"url": ref.url,
|
274
|
+
"sequenceNumber": ref.sequence_number,
|
275
|
+
"sourceId": ref.source_id,
|
276
|
+
"source": ref.source,
|
277
|
+
}
|
278
|
+
for ref in references
|
279
|
+
]
|
280
|
+
|
281
|
+
def _get_full_and_selected_history(
|
282
|
+
self,
|
283
|
+
token_limit,
|
284
|
+
percent_of_max_tokens=0.15,
|
285
|
+
max_messages=4,
|
156
286
|
):
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
max_tokens,
|
162
|
-
percent_of_max_tokens,
|
287
|
+
full_history = self._get_full_history()
|
288
|
+
selected_history = self._get_selection_from_history(
|
289
|
+
full_history,
|
290
|
+
int(round(token_limit * percent_of_max_tokens)),
|
163
291
|
max_messages,
|
164
292
|
)
|
165
293
|
|
166
|
-
|
167
|
-
|
294
|
+
return full_history, selected_history
|
295
|
+
|
296
|
+
def _get_full_history(self):
|
297
|
+
SYSTEM_MESSAGE_PREFIX = "[SYSTEM] "
|
298
|
+
|
299
|
+
messages = self._trigger_list_messages(self.state.chat_id)
|
300
|
+
|
301
|
+
# Remove the last two messages
|
302
|
+
messages = messages["data"][:-2] # type: ignore
|
303
|
+
filtered_messages = []
|
304
|
+
for message in messages:
|
305
|
+
if message["text"] is None:
|
306
|
+
continue
|
307
|
+
elif SYSTEM_MESSAGE_PREFIX in message["text"]:
|
308
|
+
continue
|
309
|
+
else:
|
310
|
+
filtered_messages.append(message)
|
311
|
+
|
312
|
+
return self._map_to_chat_messages(filtered_messages)
|
313
|
+
|
314
|
+
def _trigger_list_messages(self, chat_id: str):
|
315
|
+
try:
|
316
|
+
messages = unique_sdk.Message.list(
|
317
|
+
user_id=self.state.user_id,
|
318
|
+
company_id=self.state.company_id,
|
319
|
+
chatId=chat_id,
|
320
|
+
)
|
321
|
+
return messages
|
322
|
+
except Exception as e:
|
323
|
+
self.logger.error(f"Failed to list chat history: {e}")
|
324
|
+
raise e
|
325
|
+
|
326
|
+
@staticmethod
|
327
|
+
def _map_to_chat_messages(messages: list[dict]):
|
328
|
+
return [ChatMessage(**msg) for msg in messages]
|
329
|
+
|
330
|
+
def _get_selection_from_history(
|
168
331
|
self,
|
169
|
-
|
170
|
-
|
171
|
-
|
332
|
+
full_history: list[ChatMessage],
|
333
|
+
max_tokens: int,
|
334
|
+
max_messages=4,
|
172
335
|
):
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
role=
|
180
|
-
|
181
|
-
|
336
|
+
messages = full_history[-max_messages:]
|
337
|
+
filtered_messages = [m for m in messages if m.content]
|
338
|
+
mapped_messages = []
|
339
|
+
|
340
|
+
for m in filtered_messages:
|
341
|
+
m.content = re.sub(r"<sup>\d+</sup>", "", m.content)
|
342
|
+
m.role = (
|
343
|
+
ChatMessageRole.ASSISTANT
|
344
|
+
if m.role == ChatMessageRole.ASSISTANT
|
345
|
+
else ChatMessageRole.USER
|
346
|
+
)
|
347
|
+
mapped_messages.append(m)
|
348
|
+
|
349
|
+
return self._pick_messages_in_reverse_for_token_window(
|
350
|
+
messages=mapped_messages,
|
351
|
+
limit=max_tokens,
|
182
352
|
)
|
353
|
+
|
354
|
+
def _pick_messages_in_reverse_for_token_window(
|
355
|
+
self,
|
356
|
+
messages: list[ChatMessage],
|
357
|
+
limit: int,
|
358
|
+
) -> list[ChatMessage]:
|
359
|
+
if len(messages) < 1 or limit < 1:
|
360
|
+
return []
|
361
|
+
|
362
|
+
last_index = len(messages) - 1
|
363
|
+
token_count = count_tokens(messages[last_index].content)
|
364
|
+
while token_count > limit:
|
365
|
+
self.logger.debug(
|
366
|
+
f"Limit too low for the initial message. Last message TokenCount {token_count} available tokens {limit} - cutting message in half until it fits"
|
367
|
+
)
|
368
|
+
content = messages[last_index].content
|
369
|
+
messages[last_index].content = content[: len(content) // 2] + "..."
|
370
|
+
token_count = count_tokens(messages[last_index].content)
|
371
|
+
|
372
|
+
while token_count <= limit and last_index > 0:
|
373
|
+
token_count = count_tokens(
|
374
|
+
"".join([msg.content for msg in messages[:last_index]])
|
375
|
+
)
|
376
|
+
if token_count <= limit:
|
377
|
+
last_index -= 1
|
378
|
+
|
379
|
+
last_index = max(0, last_index)
|
380
|
+
return messages[last_index:]
|
unique_toolkit/chat/state.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
2
|
from typing import Self
|
3
3
|
|
4
|
-
from unique_toolkit.
|
4
|
+
from unique_toolkit.app.schemas import Event
|
5
5
|
|
6
6
|
|
7
7
|
@dataclass
|
@@ -13,6 +13,8 @@ class ChatState:
|
|
13
13
|
company_id (str): The company ID.
|
14
14
|
user_id (str): The user ID.
|
15
15
|
chat_id (str): The chat ID.
|
16
|
+
scope_ids (list[str] | None): The scope IDs.
|
17
|
+
chat_only (bool): The chat only flag.
|
16
18
|
user_message_text (str): The user message text.
|
17
19
|
user_message_id (str): The user message ID.
|
18
20
|
assistant_message_id (str): The assistant message ID.
|
@@ -20,29 +22,39 @@ class ChatState:
|
|
20
22
|
|
21
23
|
company_id: str
|
22
24
|
user_id: str
|
23
|
-
assistant_id: str
|
24
|
-
chat_id: str
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
assistant_id: str
|
26
|
+
chat_id: str
|
27
|
+
scope_ids: list[str] | None = None
|
28
|
+
chat_only: bool = False
|
29
|
+
user_message_text: str | None = None
|
30
|
+
user_message_id: str | None = None
|
31
|
+
assistant_message_id: str | None = None
|
32
|
+
module_name: str | None = None
|
28
33
|
|
29
34
|
@classmethod
|
30
35
|
def from_event(cls, event: Event) -> Self:
|
31
36
|
"""
|
32
|
-
Creates a ChatState instance from
|
37
|
+
Creates a ChatState instance from the Event.
|
33
38
|
|
34
39
|
Args:
|
35
|
-
event (
|
40
|
+
event (Event): The Event object.
|
36
41
|
|
37
42
|
Returns:
|
38
|
-
|
43
|
+
ChatManager: The ChatManager instance.
|
39
44
|
"""
|
40
|
-
|
45
|
+
config = event.payload.configuration
|
46
|
+
|
47
|
+
scope_ids = config.get("scopeIds") or None
|
48
|
+
chat_only = config.get("scopeToChatOnUpload", False)
|
41
49
|
return cls(
|
42
50
|
user_id=event.user_id,
|
43
51
|
chat_id=event.payload.chat_id,
|
44
52
|
company_id=event.company_id,
|
53
|
+
assistant_id=event.payload.assistant_id,
|
54
|
+
scope_ids=scope_ids,
|
55
|
+
chat_only=chat_only,
|
45
56
|
user_message_text=event.payload.user_message.text,
|
46
57
|
user_message_id=event.payload.user_message.id,
|
47
58
|
assistant_message_id=event.payload.assistant_message.id,
|
59
|
+
module_name=event.payload.name,
|
48
60
|
)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from unique_toolkit.chat.schemas import ChatMessage
|
2
|
+
from unique_toolkit.content.utils import count_tokens
|
3
|
+
|
4
|
+
|
5
|
+
def convert_chat_history_to_injectable_string(
|
6
|
+
history: list[ChatMessage],
|
7
|
+
) -> tuple[list[str], int]:
|
8
|
+
"""
|
9
|
+
Converts chat history to a string that can be injected into the model.
|
10
|
+
|
11
|
+
Args:
|
12
|
+
history (list[ChatMessage]): The chat history.
|
13
|
+
|
14
|
+
Returns:
|
15
|
+
tuple[list[str], int]: The chat history and the token length of the chat context.
|
16
|
+
"""
|
17
|
+
chatHistory = []
|
18
|
+
for msg in history:
|
19
|
+
if msg.role.value == "assistant":
|
20
|
+
chatHistory.append(f"previous_answer: {msg.content}")
|
21
|
+
else:
|
22
|
+
chatHistory.append(f"previous_question: {msg.content}")
|
23
|
+
chatContext = "\n".join(chatHistory)
|
24
|
+
chatContextTokenLength = count_tokens(chatContext)
|
25
|
+
return chatHistory, chatContextTokenLength
|
@@ -0,0 +1,90 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from enum import StrEnum
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
from humps import camelize
|
6
|
+
from pydantic import BaseModel, ConfigDict
|
7
|
+
|
8
|
+
# set config to convert camelCase to snake_case
|
9
|
+
model_config = ConfigDict(
|
10
|
+
alias_generator=camelize,
|
11
|
+
populate_by_name=True,
|
12
|
+
arbitrary_types_allowed=True,
|
13
|
+
)
|
14
|
+
|
15
|
+
|
16
|
+
class ContentMetadata(BaseModel):
|
17
|
+
model_config = model_config
|
18
|
+
key: str
|
19
|
+
mime_type: str
|
20
|
+
|
21
|
+
|
22
|
+
class ContentChunk(BaseModel):
|
23
|
+
model_config = model_config
|
24
|
+
id: str
|
25
|
+
text: str
|
26
|
+
order: int
|
27
|
+
key: str | None = None
|
28
|
+
chunk_id: str | None = None
|
29
|
+
url: str | None = None
|
30
|
+
title: str | None = None
|
31
|
+
start_page: int | None = None
|
32
|
+
end_page: int | None = None
|
33
|
+
|
34
|
+
object: str | None = None
|
35
|
+
metadata: ContentMetadata | None = None
|
36
|
+
internally_stored_at: datetime | None = None
|
37
|
+
created_at: datetime | None = None
|
38
|
+
updated_at: datetime | None = None
|
39
|
+
|
40
|
+
|
41
|
+
class Content(BaseModel):
|
42
|
+
model_config = model_config
|
43
|
+
id: str
|
44
|
+
key: str
|
45
|
+
title: str | None = None
|
46
|
+
url: str | None = None
|
47
|
+
chunks: list[ContentChunk] = []
|
48
|
+
write_url: str | None = None
|
49
|
+
read_url: str | None = None
|
50
|
+
|
51
|
+
|
52
|
+
class ContentReference(BaseModel):
|
53
|
+
model_config = model_config
|
54
|
+
id: str
|
55
|
+
message_id: str
|
56
|
+
name: str
|
57
|
+
sequence_number: int
|
58
|
+
source: str
|
59
|
+
source_id: str
|
60
|
+
url: str
|
61
|
+
|
62
|
+
|
63
|
+
class ContentSearchType(StrEnum):
|
64
|
+
COMBINED = "COMBINED"
|
65
|
+
VECTOR = "VECTOR"
|
66
|
+
|
67
|
+
|
68
|
+
class ContentSearchResult(BaseModel):
|
69
|
+
"""Schema corresponding to unique_sdk.SearchResult"""
|
70
|
+
|
71
|
+
id: str
|
72
|
+
text: str
|
73
|
+
order: int
|
74
|
+
chunkId: str | None = None
|
75
|
+
key: str | None = None
|
76
|
+
title: str | None = None
|
77
|
+
url: str | None = None
|
78
|
+
startPage: int | None = None
|
79
|
+
endPage: int | None = None
|
80
|
+
object: str | None = None
|
81
|
+
|
82
|
+
|
83
|
+
class ContentUploadInput(BaseModel):
|
84
|
+
key: str
|
85
|
+
title: str
|
86
|
+
mime_type: str
|
87
|
+
|
88
|
+
owner_type: Optional[str] = None
|
89
|
+
owner_id: Optional[str] = None
|
90
|
+
byte_size: Optional[int] = None
|