unique_toolkit 0.5.33__py3-none-any.whl → 0.5.36__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.
@@ -37,6 +37,7 @@ class EventAdditionalParameters(BaseModel):
37
37
  model_config = model_config
38
38
 
39
39
  translate_to_language: Optional[str] = None
40
+ content_id_to_translate: Optional[str] = None
40
41
 
41
42
 
42
43
  class EventPayload(BaseModel):
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import os
3
+ import re
3
4
  import tempfile
4
5
  from pathlib import Path
5
6
  from typing import Optional, Union, cast
@@ -242,6 +243,7 @@ class ContentService(BaseService):
242
243
  mime_type: str,
243
244
  scope_id: Optional[str] = None,
244
245
  chat_id: Optional[str] = None,
246
+ skip_ingestion: Optional[bool] = False,
245
247
  ):
246
248
  """
247
249
  Uploads content to the knowledge base.
@@ -264,6 +266,7 @@ class ContentService(BaseService):
264
266
  mime_type=mime_type,
265
267
  scope_id=scope_id,
266
268
  chat_id=chat_id,
269
+ skip_ingestion=skip_ingestion,
267
270
  )
268
271
  except Exception as e:
269
272
  self.logger.error(f"Error while uploading content: {e}")
@@ -276,6 +279,7 @@ class ContentService(BaseService):
276
279
  mime_type: str,
277
280
  scope_id: Optional[str] = None,
278
281
  chat_id: Optional[str] = None,
282
+ skip_ingestion: Optional[bool] = False,
279
283
  ):
280
284
  if not chat_id and not scope_id:
281
285
  raise ValueError("chat_id or scope_id must be provided")
@@ -318,16 +322,21 @@ class ContentService(BaseService):
318
322
  self.logger.error(error_msg)
319
323
  raise ValueError(error_msg)
320
324
 
325
+ input_dict = {
326
+ "key": content_name,
327
+ "title": content_name,
328
+ "mimeType": mime_type,
329
+ "byteSize": byte_size,
330
+ }
331
+
332
+ if skip_ingestion:
333
+ input_dict["ingestionConfig"] = {"uniqueIngestionMode": "SKIP_INGESTION"}
334
+
321
335
  if chat_id:
322
336
  unique_sdk.Content.upsert(
323
337
  user_id=self.event.user_id,
324
338
  company_id=self.event.company_id,
325
- input={
326
- "key": content_name,
327
- "title": content_name,
328
- "mimeType": mime_type,
329
- "byteSize": byte_size,
330
- },
339
+ input=input_dict,
331
340
  fileUrl=read_url,
332
341
  chatId=chat_id,
333
342
  ) # type: ignore
@@ -335,18 +344,95 @@ class ContentService(BaseService):
335
344
  unique_sdk.Content.upsert(
336
345
  user_id=self.event.user_id,
337
346
  company_id=self.event.company_id,
338
- input={
339
- "key": content_name,
340
- "title": content_name,
341
- "mimeType": mime_type,
342
- "byteSize": byte_size,
343
- },
347
+ input=input_dict,
344
348
  fileUrl=read_url,
345
349
  scopeId=scope_id,
346
350
  ) # type: ignore
347
351
 
348
352
  return Content(**created_content)
349
353
 
354
+ def request_content_by_id(
355
+ self, content_id: str, chat_id: str | None
356
+ ) -> requests.Response:
357
+ """
358
+ Sends a request to download content from a chat.
359
+
360
+ Args:
361
+ content_id (str): The ID of the content to download.
362
+ chat_id (str): The ID of the chat from which to download the content. Defaults to None to download from knowledge base.
363
+
364
+ Returns:
365
+ requests.Response: The response object containing the downloaded content.
366
+
367
+ """
368
+ url = f"{unique_sdk.api_base}/content/{content_id}/file"
369
+ if chat_id:
370
+ url = f"{url}?chatId={chat_id}"
371
+
372
+ # Download the file and save it to the random directory
373
+ headers = {
374
+ "x-api-version": unique_sdk.api_version,
375
+ "x-app-id": unique_sdk.app_id,
376
+ "x-user-id": self.event.user_id,
377
+ "x-company-id": self.event.company_id,
378
+ "Authorization": "Bearer %s" % (unique_sdk.api_key,),
379
+ }
380
+
381
+ return requests.get(url, headers=headers)
382
+
383
+ def download_content_to_file_by_id(
384
+ self,
385
+ content_id: str,
386
+ chat_id: Optional[str] = None,
387
+ filename: str | None = None,
388
+ tmp_dir_path: Optional[Union[str, Path]] = "/tmp",
389
+ ):
390
+ """
391
+ Downloads content from a chat and saves it to a file.
392
+
393
+ Args:
394
+ content_id (str): The ID of the content to download.
395
+ chat_id (Optional[str]): The ID of the chat to download from. Defaults to None and the file is downloaded from the knowledge base.
396
+ filename (str | None): The name of the file to save the content as. If not provided, the original filename will be used. Defaults to None.
397
+ tmp_dir_path (Optional[Union[str, Path]]): The path to the temporary directory where the content will be saved. Defaults to "/tmp".
398
+
399
+ Returns:
400
+ Path: The path to the downloaded file.
401
+
402
+ Raises:
403
+ Exception: If the download fails or the filename cannot be determined.
404
+ """
405
+
406
+ response = self.request_content_by_id(content_id, chat_id)
407
+ random_dir = tempfile.mkdtemp(dir=tmp_dir_path)
408
+
409
+ if response.status_code == 200:
410
+ if filename:
411
+ content_path = Path(random_dir) / filename
412
+ else:
413
+ pattern = r'filename="([^"]+)"'
414
+ match = re.search(
415
+ pattern, response.headers.get("Content-Disposition", "")
416
+ )
417
+ if match:
418
+ content_path = Path(random_dir) / match.group(1)
419
+ else:
420
+ error_msg = (
421
+ "Error downloading file: Filename could not be determined"
422
+ )
423
+ self.logger.error(error_msg)
424
+ raise Exception(error_msg)
425
+
426
+ with open(content_path, "wb") as file:
427
+ file.write(response.content)
428
+ else:
429
+ error_msg = f"Error downloading file: Status code {response.status_code}"
430
+ self.logger.error(error_msg)
431
+ raise Exception(error_msg)
432
+
433
+ return content_path
434
+
435
+ # TODO: Discuss if we should deprecate this method due to unclear use by content_name
350
436
  def download_content(
351
437
  self,
352
438
  content_id: str,
@@ -370,26 +456,11 @@ class ContentService(BaseService):
370
456
  Exception: If the download fails.
371
457
  """
372
458
 
373
- url = f"{unique_sdk.api_base}/content/{content_id}/file"
374
- if chat_id:
375
- url = f"{url}?chatId={chat_id}"
459
+ response = self.request_content_by_id(content_id, chat_id)
376
460
 
377
- # Create a random directory inside /tmp
378
461
  random_dir = tempfile.mkdtemp(dir=dir_path)
379
-
380
- # Create the full file path
381
462
  content_path = Path(random_dir) / content_name
382
463
 
383
- # Download the file and save it to the random directory
384
- headers = {
385
- "x-api-version": unique_sdk.api_version,
386
- "x-app-id": unique_sdk.app_id,
387
- "x-user-id": self.event.user_id,
388
- "x-company-id": self.event.company_id,
389
- "Authorization": "Bearer %s" % (unique_sdk.api_key,),
390
- }
391
-
392
- response = requests.get(url, headers=headers)
393
464
  if response.status_code == 200:
394
465
  with open(content_path, "wb") as file:
395
466
  file.write(response.content)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 0.5.33
3
+ Version: 0.5.36
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Martin Fadler
@@ -100,6 +100,16 @@ All notable changes to this project will be documented in this file.
100
100
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
101
101
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
102
102
 
103
+ ## [0.5.36] - 2024-11-19
104
+ - Add possibility to return the response from the download file from chat request
105
+ - Add possibility to not specify a filename and use filename from response headers
106
+
107
+ ## [0.5.35] - 2024-11-18
108
+ - Add the possibilty to upload files without triggering ingestion by setting `skip_ingestion` to `True` in `ContentService.upload_content`
109
+
110
+ ## [0.5.34] - 2024-11-15
111
+ - Add `content_id_to_translate` to `EventAdditionalParameters`
112
+
103
113
  ## [0.5.33] - 2024-10-30
104
114
  - Force randomizing tool_call_id. This is helpful to better identify the tool_calls.
105
115
 
@@ -8,7 +8,7 @@ unique_toolkit/app/init_logging.py,sha256=Sh26SRxOj8i8dzobKhYha2lLrkrMTHfB1V4jR3
8
8
  unique_toolkit/app/init_sdk.py,sha256=Nv4Now4pMfM0AgRhbtatLpm_39rKxn0WmRLwmPhRl-8,1285
9
9
  unique_toolkit/app/performance/async_tasks.py,sha256=H0l3OAcosLwNHZ8d2pd-Di4wHIXfclEvagi5kfqLFPA,1941
10
10
  unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
11
- unique_toolkit/app/schemas.py,sha256=tzrmUFKZUdC1P3LxZ7DrElpkMtekUDoClb7jCRzGqNQ,1521
11
+ unique_toolkit/app/schemas.py,sha256=6RY7Ex-B3pOnFILlitHEi9sqJvupbpdxlN9xt33qRsM,1571
12
12
  unique_toolkit/app/verification.py,sha256=UZqTHg3PX_QxMjeLH_BVBYoMVqMnMpeMoqvyTBKDqj8,1996
13
13
  unique_toolkit/chat/__init__.py,sha256=1prdTVfLOf6NgU-Aa1VIO-XiR6OYuRm51LaVRfKDCqc,267
14
14
  unique_toolkit/chat/schemas.py,sha256=IHOnb3pWlRlSPoEUWBTl6LK8YeMdlg2iXi9ghyBeiLw,1495
@@ -17,7 +17,7 @@ unique_toolkit/chat/state.py,sha256=Cjgwv_2vhDFbV69xxsn7SefhaoIAEqLx3ferdVFCnOg,
17
17
  unique_toolkit/chat/utils.py,sha256=ihm-wQykBWhB4liR3LnwPVPt_qGW6ETq21Mw4HY0THE,854
18
18
  unique_toolkit/content/__init__.py,sha256=MSH2sxjQyKD2Sef92fzE5Dt9SihdzivB6yliSwJfTmQ,890
19
19
  unique_toolkit/content/schemas.py,sha256=zks_Pkki2VhxICJJgHZyc-LPmRuj5dLbw3pgcUT7SW8,2362
20
- unique_toolkit/content/service.py,sha256=ZGYWYTphXpcByXyMqr1VOVUHdmdnsR-XIS_YRX0Wyv4,14211
20
+ unique_toolkit/content/service.py,sha256=e23GX2pzIppHCFPUHng-82pSELT8JKT4TRMCO6M2Lok,16968
21
21
  unique_toolkit/content/utils.py,sha256=Lake671plRsqNvO3pN_rmyVcpwbdED_KQpLcCnc4lv4,6902
22
22
  unique_toolkit/embedding/__init__.py,sha256=dr8M9jvslQTxPpxgaGwzxY0FildiWf-DidN_cahPAWw,191
23
23
  unique_toolkit/embedding/schemas.py,sha256=1GvKCaSk4jixzVQ2PKq8yDqwGEVY_hWclYtoAr6CC2g,96
@@ -40,7 +40,7 @@ unique_toolkit/language_model/infos.py,sha256=kQK6F3r8xTN7oT6b39J7rxW-Y4iPXjx_Fr
40
40
  unique_toolkit/language_model/schemas.py,sha256=0pMLM1cCplw1OlM-eLqldZtYMObGr7tjHKXSHQP7hwE,6216
41
41
  unique_toolkit/language_model/service.py,sha256=s5X6EStyYumiYqlD9gkW4GANif18d9QZOMysmUSfv8M,13433
42
42
  unique_toolkit/language_model/utils.py,sha256=WBPj1XKkDgxy_-T8HCZvsfkkSzj_1w4UZzNmyvdbBLY,1081
43
- unique_toolkit-0.5.33.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
44
- unique_toolkit-0.5.33.dist-info/METADATA,sha256=c063R7-la1op6nRW1W2IIFdQrl21NA_P3JmorSbNV8Y,13190
45
- unique_toolkit-0.5.33.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
46
- unique_toolkit-0.5.33.dist-info/RECORD,,
43
+ unique_toolkit-0.5.36.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
44
+ unique_toolkit-0.5.36.dist-info/METADATA,sha256=4YTkAbPH4uPA3IxsLyxr4-eI3wvn8LLJTAxhO-UDNTw,13635
45
+ unique_toolkit-0.5.36.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
46
+ unique_toolkit-0.5.36.dist-info/RECORD,,