unique_sdk 0.10.1__tar.gz → 0.10.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/CHANGELOG.md +3 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/PKG-INFO +68 -28
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/README.md +64 -27
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/pyproject.toml +1 -1
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_content.py +11 -10
- unique_sdk-0.10.2/unique_sdk/utils/chat_in_space.py +167 -0
- unique_sdk-0.10.1/unique_sdk/utils/chat_in_space.py +0 -53
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/LICENSE +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/__init__.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_api_requestor.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_api_resource.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_api_version.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_error.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_http_client.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_list_object.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_object_classes.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_request_options.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_unique_object.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_unique_ql.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_unique_response.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_util.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_version.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_webhook.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/__init__.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_acronyms.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_chat_completion.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_embedding.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_event.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_folder.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_integrated.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_mcp.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_message.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_message_assessment.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_search.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_search_string.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_short_term_memory.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_space.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/chat_history.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/file_io.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/sources.py +0 -0
- {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/token.py +0 -0
|
@@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.10.2] - 2025-08-05
|
|
9
|
+
- Add script to chat against file.
|
|
10
|
+
|
|
8
11
|
## [0.10.1] - 2025-08-05
|
|
9
12
|
- Allow deletion of a space chat.
|
|
10
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: unique_sdk
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Martin Fadler
|
|
@@ -1024,6 +1024,12 @@ A metadata filter such as the one designed above can be used in a `Search.create
|
|
|
1024
1024
|
|
|
1025
1025
|
## Utils
|
|
1026
1026
|
|
|
1027
|
+
- [Chat History](#chat-history)
|
|
1028
|
+
- [File Io](#file-io)
|
|
1029
|
+
- [Sources](#sources)
|
|
1030
|
+
- [token](#token)
|
|
1031
|
+
- [Chat In Space](#chat-in-space)
|
|
1032
|
+
|
|
1027
1033
|
### Chat History
|
|
1028
1034
|
|
|
1029
1035
|
#### `unique_sdk.utils.chat_history.load_history`
|
|
@@ -1253,33 +1259,64 @@ The script ensures you can flexibly interact with spaces in new or ongoing chats
|
|
|
1253
1259
|
|
|
1254
1260
|
```python
|
|
1255
1261
|
latest_message = await unique_sdk.utils.chat_in_space.send_message_and_wait_for_completion(
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1262
|
+
user_id=user_id,
|
|
1263
|
+
company_id=company_id,
|
|
1264
|
+
assistant_id=assistant_id,
|
|
1265
|
+
text="Tell me a short story.",
|
|
1266
|
+
chat_id=chat_id, # Optional - if no chat id is specified, a new chat will be created
|
|
1267
|
+
tool_choices=["WebSearch"],
|
|
1268
|
+
scope_rules={
|
|
1269
|
+
"or": [
|
|
1270
|
+
{
|
|
1271
|
+
"operator": "in",
|
|
1272
|
+
"path": [
|
|
1273
|
+
"contentId"
|
|
1274
|
+
],
|
|
1275
|
+
"value": [
|
|
1276
|
+
"cont_u888z7cazxxm4lugfdjq7pks"
|
|
1277
|
+
]
|
|
1278
|
+
},
|
|
1279
|
+
{
|
|
1280
|
+
"operator": "contains",
|
|
1281
|
+
"path": [
|
|
1282
|
+
"folderIdPath"
|
|
1283
|
+
],
|
|
1284
|
+
"value": "uniquepathid://scope_btfo28b3eeelwh5obwgea71bl/scope_fn56ta67knd6w4medgq3028fx"
|
|
1285
|
+
}
|
|
1286
|
+
]
|
|
1287
|
+
},
|
|
1288
|
+
)
|
|
1289
|
+
```
|
|
1290
|
+
|
|
1291
|
+
#### `unique_sdk.utils.chat_in_space.chat_against_file`
|
|
1292
|
+
|
|
1293
|
+
The following script enables you to chat against a file.
|
|
1294
|
+
|
|
1295
|
+
You must provide the following parameters:
|
|
1296
|
+
- `assistantId`: The assistant to be used for the chat.
|
|
1297
|
+
- `path_to_file`: The local path of the file to be uploaded.
|
|
1298
|
+
- `displayed_filename`: The name of the file to be displayed.
|
|
1299
|
+
- `mime_type`: The mime type of the ifle to be uploaded.
|
|
1300
|
+
- `text`: The text to be sent to the chat for chatting against the file.
|
|
1301
|
+
|
|
1302
|
+
The script creates a chat and uploads the file to it. It then keeps polling the `ingestionState` field of the message, waiting for it to reach `FINISHED`, signaling the upload is complete. Once the file uploads successfully, the script sends the text, continues polling for completion, and finally retrieves the response message.
|
|
1303
|
+
|
|
1304
|
+
**Optional parameters:**
|
|
1305
|
+
- `poll_interval`: The number of seconds to wait between polling attempts (default: `1` second).
|
|
1306
|
+
- `max_wait`: The maximum number of seconds to wait for the message to complete (default: `60` seconds).
|
|
1307
|
+
|
|
1308
|
+
Example of chatting against a PDF. (The usage can be extended to any supported file type)
|
|
1309
|
+
|
|
1310
|
+
```python
|
|
1311
|
+
latest_message = await unique_sdk.utils.chat_in_space.chat_against_file(
|
|
1312
|
+
user_id=user_id,
|
|
1313
|
+
company_id=company_id,
|
|
1314
|
+
assistant_id="assistant_hjcdga64bkcjnhu4",
|
|
1315
|
+
path_to_file="/files/hello.pdf",
|
|
1316
|
+
displayed_filename="hello.pdf"
|
|
1317
|
+
mime_type="application/pdf"
|
|
1318
|
+
text="Give me a bullet point summary of the file.",
|
|
1319
|
+
)
|
|
1283
1320
|
```
|
|
1284
1321
|
|
|
1285
1322
|
## Error Handling
|
|
@@ -1299,6 +1336,9 @@ All notable changes to this project will be documented in this file.
|
|
|
1299
1336
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
1300
1337
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
1301
1338
|
|
|
1339
|
+
## [0.10.2] - 2025-08-05
|
|
1340
|
+
- Add script to chat against file.
|
|
1341
|
+
|
|
1302
1342
|
## [0.10.1] - 2025-08-05
|
|
1303
1343
|
- Allow deletion of a space chat.
|
|
1304
1344
|
|
|
@@ -1008,6 +1008,12 @@ A metadata filter such as the one designed above can be used in a `Search.create
|
|
|
1008
1008
|
|
|
1009
1009
|
## Utils
|
|
1010
1010
|
|
|
1011
|
+
- [Chat History](#chat-history)
|
|
1012
|
+
- [File Io](#file-io)
|
|
1013
|
+
- [Sources](#sources)
|
|
1014
|
+
- [token](#token)
|
|
1015
|
+
- [Chat In Space](#chat-in-space)
|
|
1016
|
+
|
|
1011
1017
|
### Chat History
|
|
1012
1018
|
|
|
1013
1019
|
#### `unique_sdk.utils.chat_history.load_history`
|
|
@@ -1237,33 +1243,64 @@ The script ensures you can flexibly interact with spaces in new or ongoing chats
|
|
|
1237
1243
|
|
|
1238
1244
|
```python
|
|
1239
1245
|
latest_message = await unique_sdk.utils.chat_in_space.send_message_and_wait_for_completion(
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1246
|
+
user_id=user_id,
|
|
1247
|
+
company_id=company_id,
|
|
1248
|
+
assistant_id=assistant_id,
|
|
1249
|
+
text="Tell me a short story.",
|
|
1250
|
+
chat_id=chat_id, # Optional - if no chat id is specified, a new chat will be created
|
|
1251
|
+
tool_choices=["WebSearch"],
|
|
1252
|
+
scope_rules={
|
|
1253
|
+
"or": [
|
|
1254
|
+
{
|
|
1255
|
+
"operator": "in",
|
|
1256
|
+
"path": [
|
|
1257
|
+
"contentId"
|
|
1258
|
+
],
|
|
1259
|
+
"value": [
|
|
1260
|
+
"cont_u888z7cazxxm4lugfdjq7pks"
|
|
1261
|
+
]
|
|
1262
|
+
},
|
|
1263
|
+
{
|
|
1264
|
+
"operator": "contains",
|
|
1265
|
+
"path": [
|
|
1266
|
+
"folderIdPath"
|
|
1267
|
+
],
|
|
1268
|
+
"value": "uniquepathid://scope_btfo28b3eeelwh5obwgea71bl/scope_fn56ta67knd6w4medgq3028fx"
|
|
1269
|
+
}
|
|
1270
|
+
]
|
|
1271
|
+
},
|
|
1272
|
+
)
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
#### `unique_sdk.utils.chat_in_space.chat_against_file`
|
|
1276
|
+
|
|
1277
|
+
The following script enables you to chat against a file.
|
|
1278
|
+
|
|
1279
|
+
You must provide the following parameters:
|
|
1280
|
+
- `assistantId`: The assistant to be used for the chat.
|
|
1281
|
+
- `path_to_file`: The local path of the file to be uploaded.
|
|
1282
|
+
- `displayed_filename`: The name of the file to be displayed.
|
|
1283
|
+
- `mime_type`: The mime type of the ifle to be uploaded.
|
|
1284
|
+
- `text`: The text to be sent to the chat for chatting against the file.
|
|
1285
|
+
|
|
1286
|
+
The script creates a chat and uploads the file to it. It then keeps polling the `ingestionState` field of the message, waiting for it to reach `FINISHED`, signaling the upload is complete. Once the file uploads successfully, the script sends the text, continues polling for completion, and finally retrieves the response message.
|
|
1287
|
+
|
|
1288
|
+
**Optional parameters:**
|
|
1289
|
+
- `poll_interval`: The number of seconds to wait between polling attempts (default: `1` second).
|
|
1290
|
+
- `max_wait`: The maximum number of seconds to wait for the message to complete (default: `60` seconds).
|
|
1291
|
+
|
|
1292
|
+
Example of chatting against a PDF. (The usage can be extended to any supported file type)
|
|
1293
|
+
|
|
1294
|
+
```python
|
|
1295
|
+
latest_message = await unique_sdk.utils.chat_in_space.chat_against_file(
|
|
1296
|
+
user_id=user_id,
|
|
1297
|
+
company_id=company_id,
|
|
1298
|
+
assistant_id="assistant_hjcdga64bkcjnhu4",
|
|
1299
|
+
path_to_file="/files/hello.pdf",
|
|
1300
|
+
displayed_filename="hello.pdf"
|
|
1301
|
+
mime_type="application/pdf"
|
|
1302
|
+
text="Give me a bullet point summary of the file.",
|
|
1303
|
+
)
|
|
1267
1304
|
```
|
|
1268
1305
|
|
|
1269
1306
|
## Error Handling
|
|
@@ -64,6 +64,7 @@ class Content(APIResource["Content"]):
|
|
|
64
64
|
class SearchParams(RequestOptions):
|
|
65
65
|
where: "Content.ContentWhereInput"
|
|
66
66
|
chatId: NotRequired[str]
|
|
67
|
+
includeFailedContent: NotRequired[bool]
|
|
67
68
|
|
|
68
69
|
class ContentInfoParams(TypedDict):
|
|
69
70
|
"""
|
|
@@ -163,11 +164,11 @@ class Content(APIResource["Content"]):
|
|
|
163
164
|
class MagicTableSheetTable(TypedDict):
|
|
164
165
|
rowId: str
|
|
165
166
|
columns: List["Content.MagicTableSheetTableColumn"]
|
|
166
|
-
|
|
167
|
+
|
|
167
168
|
class MagicTableSheetIngestionConfiguration(TypedDict):
|
|
168
169
|
columnIdsInMetadata: List[str]
|
|
169
170
|
columnIdsInChunkText: List[str]
|
|
170
|
-
|
|
171
|
+
|
|
171
172
|
class MagicTableSheetIngestParams(TypedDict):
|
|
172
173
|
data: List["Content.MagicTableSheetTable"]
|
|
173
174
|
ingestionConfiguration: "Content.MagicTableSheetIngestionConfiguration"
|
|
@@ -298,10 +299,10 @@ class Content(APIResource["Content"]):
|
|
|
298
299
|
|
|
299
300
|
@classmethod
|
|
300
301
|
def ingest_magic_table_sheets(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
302
|
+
cls,
|
|
303
|
+
user_id: str,
|
|
304
|
+
company_id: str,
|
|
305
|
+
**params: Unpack["Content.MagicTableSheetIngestParams"],
|
|
305
306
|
) -> "Content.MagicTableSheetResponse":
|
|
306
307
|
return cast(
|
|
307
308
|
Content.MagicTableSheetResponse,
|
|
@@ -316,10 +317,10 @@ class Content(APIResource["Content"]):
|
|
|
316
317
|
|
|
317
318
|
@classmethod
|
|
318
319
|
async def ingest_magic_table_sheets_async(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
320
|
+
cls,
|
|
321
|
+
user_id: str,
|
|
322
|
+
company_id: str,
|
|
323
|
+
**params: Unpack["Content.MagicTableSheetIngestParams"],
|
|
323
324
|
) -> "Content.MagicTableSheetResponse":
|
|
324
325
|
return cast(
|
|
325
326
|
Content.MagicTableSheetResponse,
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from unique_sdk.api_resources._content import Content
|
|
5
|
+
from unique_sdk.api_resources._space import Space
|
|
6
|
+
from unique_sdk.utils.file_io import upload_file
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def send_message_and_wait_for_completion(
|
|
10
|
+
user_id: str,
|
|
11
|
+
company_id: str,
|
|
12
|
+
assistant_id: str,
|
|
13
|
+
text: str,
|
|
14
|
+
tool_choices: List[str] = None,
|
|
15
|
+
scope_rules: dict | None = None,
|
|
16
|
+
chat_id: str = None,
|
|
17
|
+
poll_interval: float = 1.0,
|
|
18
|
+
max_wait: float = 60.0,
|
|
19
|
+
) -> "Space.Message":
|
|
20
|
+
"""
|
|
21
|
+
Sends a prompt asynchronously and polls for completion. (until stoppedStreamingAt is not None)
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
user_id: The user ID.
|
|
25
|
+
company_id: The company ID.
|
|
26
|
+
assistant_id: The assistant ID.
|
|
27
|
+
text: The prompt text.
|
|
28
|
+
poll_interval: Seconds between polls.
|
|
29
|
+
max_wait: Maximum seconds to wait for completion.
|
|
30
|
+
**kwargs: Additional parameters for the prompt.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The completed Space.Message.
|
|
34
|
+
"""
|
|
35
|
+
response = await Space.create_message_async(
|
|
36
|
+
user_id=user_id,
|
|
37
|
+
company_id=company_id,
|
|
38
|
+
assistantId=assistant_id,
|
|
39
|
+
chatId=chat_id,
|
|
40
|
+
text=text,
|
|
41
|
+
toolChoices=tool_choices,
|
|
42
|
+
scopeRules=scope_rules,
|
|
43
|
+
)
|
|
44
|
+
chat_id = response.get("chatId")
|
|
45
|
+
|
|
46
|
+
max_attempts = int(max_wait // poll_interval)
|
|
47
|
+
for _ in range(max_attempts):
|
|
48
|
+
answer = Space.get_latest_message(user_id, company_id, chat_id)
|
|
49
|
+
if answer.get("stoppedStreamingAt") is not None:
|
|
50
|
+
return answer
|
|
51
|
+
await asyncio.sleep(poll_interval)
|
|
52
|
+
|
|
53
|
+
raise TimeoutError("Timed out waiting for prompt completion.")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def chat_against_file(
|
|
57
|
+
user_id: str,
|
|
58
|
+
company_id: str,
|
|
59
|
+
assistant_id: str,
|
|
60
|
+
path_to_file: str,
|
|
61
|
+
displayed_filename: str,
|
|
62
|
+
mime_type: str,
|
|
63
|
+
text: str,
|
|
64
|
+
poll_interval: float = 1.0,
|
|
65
|
+
max_wait: float = 60.0,
|
|
66
|
+
) -> "Space.Message":
|
|
67
|
+
"""
|
|
68
|
+
Chat against a file by uploading it, sending a message and waiting for a reply.
|
|
69
|
+
Args:
|
|
70
|
+
|
|
71
|
+
user_id: The user ID.
|
|
72
|
+
company_id: The company ID.
|
|
73
|
+
assistant_id: The assistant ID.
|
|
74
|
+
path_to_file: Path to the PDF file to upload.
|
|
75
|
+
displayed_filename: Name to display for the uploaded file.
|
|
76
|
+
mime_type: MIME type of the file (e.g., "application/pdf").
|
|
77
|
+
text: Text to send after uploading the file and chat against.
|
|
78
|
+
poll_interval: Seconds between polls for file ingestion.
|
|
79
|
+
max_wait: Maximum seconds to wait for the final response.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
The final message response.
|
|
83
|
+
"""
|
|
84
|
+
chat_id = None
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
response = await send_message_and_wait_for_completion(
|
|
88
|
+
user_id=user_id,
|
|
89
|
+
company_id=company_id,
|
|
90
|
+
assistant_id=assistant_id,
|
|
91
|
+
text="I'm going to upload a file for analysis.",
|
|
92
|
+
)
|
|
93
|
+
chat_id = response.get("chatId")
|
|
94
|
+
|
|
95
|
+
upload_response = upload_file(
|
|
96
|
+
userId=user_id,
|
|
97
|
+
companyId=company_id,
|
|
98
|
+
path_to_file=path_to_file,
|
|
99
|
+
displayed_filename=displayed_filename,
|
|
100
|
+
mime_type=mime_type,
|
|
101
|
+
chat_id=chat_id,
|
|
102
|
+
)
|
|
103
|
+
content_id = upload_response.get("id")
|
|
104
|
+
|
|
105
|
+
await wait_for_ingestion_completion(
|
|
106
|
+
user_id=user_id,
|
|
107
|
+
company_id=company_id,
|
|
108
|
+
content_id=content_id,
|
|
109
|
+
chat_id=chat_id,
|
|
110
|
+
poll_interval=poll_interval,
|
|
111
|
+
max_wait=max_wait,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
final_response = await send_message_and_wait_for_completion(
|
|
115
|
+
user_id=user_id,
|
|
116
|
+
company_id=company_id,
|
|
117
|
+
assistant_id=assistant_id,
|
|
118
|
+
text=text,
|
|
119
|
+
chat_id=chat_id,
|
|
120
|
+
poll_interval=poll_interval,
|
|
121
|
+
max_wait=max_wait,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return final_response
|
|
125
|
+
|
|
126
|
+
except Exception as err:
|
|
127
|
+
print(f"Error during chat against file: {err}")
|
|
128
|
+
raise
|
|
129
|
+
finally:
|
|
130
|
+
if chat_id:
|
|
131
|
+
Space.delete_chat(
|
|
132
|
+
user_id=user_id,
|
|
133
|
+
company_id=company_id,
|
|
134
|
+
chat_id=chat_id,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
async def wait_for_ingestion_completion(
|
|
139
|
+
user_id: str,
|
|
140
|
+
company_id: str,
|
|
141
|
+
content_id: str,
|
|
142
|
+
chat_id: str,
|
|
143
|
+
poll_interval: float = 1.0,
|
|
144
|
+
max_wait: float = 60.0,
|
|
145
|
+
):
|
|
146
|
+
"""
|
|
147
|
+
Waits until the content ingestionState is FINISHED or the maximum wait time is reached and throws if case of failed status.
|
|
148
|
+
"""
|
|
149
|
+
max_attempts = int(max_wait // poll_interval)
|
|
150
|
+
for _ in range(max_attempts):
|
|
151
|
+
searched_content = Content.search(
|
|
152
|
+
user_id=user_id,
|
|
153
|
+
company_id=company_id,
|
|
154
|
+
where={"id": {"equals": content_id}},
|
|
155
|
+
chatId=chat_id,
|
|
156
|
+
includeFailedContent=True,
|
|
157
|
+
)
|
|
158
|
+
if searched_content:
|
|
159
|
+
ingestion_state = searched_content[0].get("ingestionState")
|
|
160
|
+
if ingestion_state == "FINISHED":
|
|
161
|
+
return
|
|
162
|
+
if isinstance(ingestion_state, str) and ingestion_state.startswith(
|
|
163
|
+
"FAILED"
|
|
164
|
+
):
|
|
165
|
+
raise RuntimeError(f"Ingestion failed with state: {ingestion_state}")
|
|
166
|
+
await asyncio.sleep(poll_interval)
|
|
167
|
+
raise TimeoutError("Timed out waiting for file ingestion to finish.")
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
from typing import List
|
|
3
|
-
|
|
4
|
-
from unique_sdk.api_resources._space import Space
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
async def send_message_and_wait_for_completion(
|
|
8
|
-
user_id: str,
|
|
9
|
-
company_id: str,
|
|
10
|
-
assistant_id: str,
|
|
11
|
-
text: str,
|
|
12
|
-
tool_choices: List[str] = None,
|
|
13
|
-
scope_rules: dict | None = None,
|
|
14
|
-
chat_id: str = None,
|
|
15
|
-
poll_interval: float = 1.0,
|
|
16
|
-
max_wait: float = 60.0,
|
|
17
|
-
) -> "Space.Message":
|
|
18
|
-
"""
|
|
19
|
-
Sends a prompt asynchronously and polls for completion. (until stoppedStreamingAt is not None)
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
user_id: The user ID.
|
|
23
|
-
company_id: The company ID.
|
|
24
|
-
assistant_id: The assistant ID.
|
|
25
|
-
text: The prompt text.
|
|
26
|
-
poll_interval: Seconds between polls.
|
|
27
|
-
max_wait: Maximum seconds to wait for completion.
|
|
28
|
-
**kwargs: Additional parameters for the prompt.
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
The completed Space.Message.
|
|
32
|
-
"""
|
|
33
|
-
# Send the prompt asynchronously
|
|
34
|
-
response = await Space.create_message_async(
|
|
35
|
-
user_id=user_id,
|
|
36
|
-
company_id=company_id,
|
|
37
|
-
assistantId=assistant_id,
|
|
38
|
-
chatId=chat_id,
|
|
39
|
-
text=text,
|
|
40
|
-
toolChoices=tool_choices,
|
|
41
|
-
scopeRules=scope_rules,
|
|
42
|
-
)
|
|
43
|
-
chat_id = response.get("chatId")
|
|
44
|
-
|
|
45
|
-
max_attempts = int(max_wait // poll_interval)
|
|
46
|
-
for _ in range(max_attempts):
|
|
47
|
-
# Poll for the answer
|
|
48
|
-
answer = Space.get_latest_message(user_id, company_id, chat_id)
|
|
49
|
-
if answer.get("stoppedStreamingAt") is not None:
|
|
50
|
-
return answer
|
|
51
|
-
await asyncio.sleep(poll_interval)
|
|
52
|
-
|
|
53
|
-
raise TimeoutError("Timed out waiting for prompt completion.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|