unique_toolkit 0.0.2__py3-none-any.whl → 0.5.1__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/app/init_logging.py +31 -0
- unique_toolkit/app/init_sdk.py +41 -0
- unique_toolkit/app/performance/async_executor.py +186 -0
- unique_toolkit/app/performance/async_wrapper.py +28 -0
- unique_toolkit/app/schemas.py +54 -0
- unique_toolkit/app/verification.py +58 -0
- unique_toolkit/chat/schemas.py +30 -0
- unique_toolkit/chat/service.py +380 -0
- unique_toolkit/chat/state.py +60 -0
- 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.5.1.dist-info/METADATA +138 -0
- unique_toolkit-0.5.1.dist-info/RECORD +24 -0
- unique_toolkit-0.0.2.dist-info/METADATA +0 -33
- unique_toolkit-0.0.2.dist-info/RECORD +0 -5
- {unique_toolkit-0.0.2.dist-info → unique_toolkit-0.5.1.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.0.2.dist-info → unique_toolkit-0.5.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,380 @@
|
|
1
|
+
import logging
|
2
|
+
import re
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
import unique_sdk
|
6
|
+
|
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
|
12
|
+
|
13
|
+
|
14
|
+
class ChatService:
|
15
|
+
"""
|
16
|
+
Provides all functionalities to manage the chat session.
|
17
|
+
|
18
|
+
Attributes:
|
19
|
+
state (ChatState): The chat state.
|
20
|
+
logger (Optional[logging.Logger]): The logger. Defaults to None.
|
21
|
+
"""
|
22
|
+
|
23
|
+
def __init__(self, state: ChatState, logger: Optional[logging.Logger] = None):
|
24
|
+
self.state = state
|
25
|
+
self.logger = logger or logging.getLogger(__name__)
|
26
|
+
|
27
|
+
def modify_assistant_message(
|
28
|
+
self,
|
29
|
+
content: str,
|
30
|
+
references: list[ContentReference] = [],
|
31
|
+
debug_info: dict = {},
|
32
|
+
message_id: Optional[str] = None,
|
33
|
+
) -> ChatMessage:
|
34
|
+
"""
|
35
|
+
Modifies a message in the chat session synchronously.
|
36
|
+
|
37
|
+
Args:
|
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.
|
48
|
+
"""
|
49
|
+
return self._trigger_modify_assistant_message(
|
50
|
+
content=content,
|
51
|
+
message_id=message_id,
|
52
|
+
references=references,
|
53
|
+
debug_info=debug_info,
|
54
|
+
)
|
55
|
+
|
56
|
+
@to_async
|
57
|
+
@async_warning
|
58
|
+
def async_modify_assistant_message(
|
59
|
+
self,
|
60
|
+
content: str,
|
61
|
+
references: list[ContentReference] = [],
|
62
|
+
debug_info: dict = {},
|
63
|
+
message_id: Optional[str] = None,
|
64
|
+
) -> ChatMessage:
|
65
|
+
"""
|
66
|
+
Modifies a message in the chat session asynchronously.
|
67
|
+
|
68
|
+
Args:
|
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.
|
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.
|
96
|
+
"""
|
97
|
+
return self._get_full_history()
|
98
|
+
|
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(
|
114
|
+
self,
|
115
|
+
token_limit: int,
|
116
|
+
percent_of_max_tokens: float,
|
117
|
+
max_messages: int,
|
118
|
+
) -> tuple[list[ChatMessage], list[ChatMessage]]:
|
119
|
+
"""
|
120
|
+
Loads the chat history for the chat session synchronously.
|
121
|
+
|
122
|
+
Args:
|
123
|
+
token_limit (int): The maximum number of tokens to load.
|
124
|
+
percent_of_max_tokens (float): The percentage of the maximum tokens to load.
|
125
|
+
max_messages (int): The maximum number of messages to load.
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
tuple[list[ChatMessage], list[ChatMessage]]: The selected and full chat history.
|
129
|
+
|
130
|
+
Raises:
|
131
|
+
Exception: If the loading fails.
|
132
|
+
"""
|
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,
|
137
|
+
)
|
138
|
+
|
139
|
+
@to_async
|
140
|
+
@async_warning
|
141
|
+
def async_get_full_and_selected_history(
|
142
|
+
self,
|
143
|
+
token_limit: int,
|
144
|
+
percent_of_max_tokens: float,
|
145
|
+
max_messages: int,
|
146
|
+
) -> tuple[list[ChatMessage], list[ChatMessage]]:
|
147
|
+
"""
|
148
|
+
Loads the chat history for the chat session asynchronously.
|
149
|
+
|
150
|
+
Args:
|
151
|
+
token_limit (int): The maximum number of tokens to load.
|
152
|
+
percent_of_max_tokens (float): The percentage of the maximum tokens to load.
|
153
|
+
max_messages (int): The maximum number of messages to load.
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
tuple[list[ChatMessage], list[ChatMessage]]: The selected and full chat history.
|
157
|
+
|
158
|
+
Raises:
|
159
|
+
Exception: If the loading fails.
|
160
|
+
"""
|
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,
|
165
|
+
)
|
166
|
+
|
167
|
+
def create_assistant_message(
|
168
|
+
self,
|
169
|
+
content: str,
|
170
|
+
references: list[ContentReference] = [],
|
171
|
+
debug_info: dict = {},
|
172
|
+
):
|
173
|
+
"""
|
174
|
+
Creates a message in the chat session synchronously.
|
175
|
+
|
176
|
+
Args:
|
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.
|
186
|
+
"""
|
187
|
+
return self._trigger_create_assistant_message(
|
188
|
+
content=content,
|
189
|
+
references=references,
|
190
|
+
debug_info=debug_info,
|
191
|
+
)
|
192
|
+
|
193
|
+
@to_async
|
194
|
+
@async_warning
|
195
|
+
def async_create_assistant_message(
|
196
|
+
self,
|
197
|
+
content: str,
|
198
|
+
references: list[ContentReference] = [],
|
199
|
+
debug_info: dict = {},
|
200
|
+
):
|
201
|
+
"""
|
202
|
+
Creates a message in the chat session asynchronously.
|
203
|
+
|
204
|
+
Args:
|
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.
|
214
|
+
"""
|
215
|
+
|
216
|
+
return self._trigger_create_assistant_message(
|
217
|
+
content=content,
|
218
|
+
references=references,
|
219
|
+
debug_info=debug_info,
|
220
|
+
)
|
221
|
+
|
222
|
+
def _trigger_modify_assistant_message(
|
223
|
+
self,
|
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)
|
245
|
+
|
246
|
+
def _trigger_create_assistant_message(
|
247
|
+
self,
|
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,
|
286
|
+
):
|
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)),
|
291
|
+
max_messages,
|
292
|
+
)
|
293
|
+
|
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(
|
331
|
+
self,
|
332
|
+
full_history: list[ChatMessage],
|
333
|
+
max_tokens: int,
|
334
|
+
max_messages=4,
|
335
|
+
):
|
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,
|
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:]
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import Self
|
3
|
+
|
4
|
+
from unique_toolkit.app.schemas import Event
|
5
|
+
|
6
|
+
|
7
|
+
@dataclass
|
8
|
+
class ChatState:
|
9
|
+
"""
|
10
|
+
Represents the state of the chat session.
|
11
|
+
|
12
|
+
Attributes:
|
13
|
+
company_id (str): The company ID.
|
14
|
+
user_id (str): The user ID.
|
15
|
+
chat_id (str): The chat ID.
|
16
|
+
scope_ids (list[str] | None): The scope IDs.
|
17
|
+
chat_only (bool): The chat only flag.
|
18
|
+
user_message_text (str): The user message text.
|
19
|
+
user_message_id (str): The user message ID.
|
20
|
+
assistant_message_id (str): The assistant message ID.
|
21
|
+
"""
|
22
|
+
|
23
|
+
company_id: str
|
24
|
+
user_id: str
|
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
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
def from_event(cls, event: Event) -> Self:
|
36
|
+
"""
|
37
|
+
Creates a ChatState instance from the Event.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
event (Event): The Event object.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
ChatManager: The ChatManager instance.
|
44
|
+
"""
|
45
|
+
config = event.payload.configuration
|
46
|
+
|
47
|
+
scope_ids = config.get("scopeIds") or None
|
48
|
+
chat_only = config.get("scopeToChatOnUpload", False)
|
49
|
+
return cls(
|
50
|
+
user_id=event.user_id,
|
51
|
+
chat_id=event.payload.chat_id,
|
52
|
+
company_id=event.company_id,
|
53
|
+
assistant_id=event.payload.assistant_id,
|
54
|
+
scope_ids=scope_ids,
|
55
|
+
chat_only=chat_only,
|
56
|
+
user_message_text=event.payload.user_message.text,
|
57
|
+
user_message_id=event.payload.user_message.id,
|
58
|
+
assistant_message_id=event.payload.assistant_message.id,
|
59
|
+
module_name=event.payload.name,
|
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
|