unique_sdk 0.9.23__tar.gz → 0.9.28__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.
Files changed (36) hide show
  1. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/CHANGELOG.md +14 -0
  2. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/PKG-INFO +115 -18
  3. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/README.md +99 -17
  4. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/pyproject.toml +3 -1
  5. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_content.py +92 -1
  6. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_search.py +1 -1
  7. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/utils/file_io.py +11 -1
  8. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/LICENSE +0 -0
  9. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/__init__.py +0 -0
  10. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_api_requestor.py +0 -0
  11. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_api_resource.py +0 -0
  12. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_api_version.py +0 -0
  13. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_error.py +0 -0
  14. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_http_client.py +0 -0
  15. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_list_object.py +0 -0
  16. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_object_classes.py +0 -0
  17. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_request_options.py +0 -0
  18. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_unique_object.py +0 -0
  19. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_unique_ql.py +0 -0
  20. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_unique_response.py +0 -0
  21. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_util.py +0 -0
  22. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_version.py +0 -0
  23. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/_webhook.py +0 -0
  24. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/__init__.py +0 -0
  25. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_acronyms.py +0 -0
  26. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_chat_completion.py +0 -0
  27. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_embedding.py +0 -0
  28. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_event.py +0 -0
  29. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_integrated.py +0 -0
  30. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_message.py +0 -0
  31. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_message_assessment.py +0 -0
  32. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_search_string.py +0 -0
  33. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/api_resources/_short_term_memory.py +0 -0
  34. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/utils/chat_history.py +0 -0
  35. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/utils/sources.py +0 -0
  36. {unique_sdk-0.9.23 → unique_sdk-0.9.28}/unique_sdk/utils/token.py +0 -0
@@ -5,6 +5,20 @@ 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.9.28] - 2025-05-20
9
+ - Add function to search content info. This also allows filtering content info by metadata info.
10
+
11
+ ## [0.9.27] - 2025-05-14
12
+ - Add the possibility to specify metadata when creating or updating a Content.
13
+
14
+ ## [0.9.26] - 2025-05-13
15
+ - Add the possibility to specify ingestionConfig when creating or updating a Content.
16
+
17
+ ## [0.9.25] - 2025-05-02
18
+ - Fixed typos in `README.md`, including incorrect `sdk.utils` imports and code example errors.
19
+
20
+ ## [0.9.24] - 2025-04-23
21
+ - Make `chatId` property in `Search.CreateParams` optional
8
22
 
9
23
  ## [0.9.23] - 2025-03-25
10
24
  - Define programming language classifier explicitly for python 3.11
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_sdk
3
- Version: 0.9.23
3
+ Version: 0.9.28
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Martin Fadler
@@ -10,6 +10,7 @@ Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
13
14
  Requires-Dist: typing-extensions (>=4.9.0,<5.0.0)
14
15
  Description-Content-Type: text/markdown
15
16
 
@@ -282,6 +283,73 @@ unique_sdk.Content.search(
282
283
  )
283
284
  ```
284
285
 
286
+ #### `unique_sdk.Content.get_info`
287
+
288
+ Allows you to get content info. To filter the results you can define a metadata filter in UniqueQL language. Find out more about it in the UniqueQL section. An example of a metadata filter defined with UniqueQL is the following:
289
+
290
+ ```python
291
+ metadataFilter: {
292
+ "or": [
293
+ {
294
+ "and": [
295
+ {
296
+ "operator": "contains",
297
+ "path": [
298
+ "folderIdPath"
299
+ ],
300
+ "value": "uniquepathid://test_id"
301
+ },
302
+ {
303
+ "operator": "contains",
304
+ "path": [
305
+ "title"
306
+ ],
307
+ "value": "ai"
308
+ }
309
+ ]
310
+ }
311
+ ]
312
+ },
313
+ ```
314
+
315
+ Pagination is also enabled for this functionality, and the default number of returned results is 50 with no entries skipped. Use the following paramteres to get the desired page:`
316
+
317
+ - `skip`
318
+ - `take`
319
+
320
+ Here is an example of retrieving the first 3 content infos that contain the value `uniquepathid://scope_abcdibgznc4bkdcx120zm5d` in the `folderIdPath` metadata and the value `ai` for the `tile` metadata.
321
+
322
+ ```python
323
+ content_info_result = unique_sdk.Content.get_info(
324
+ user_id=user_id,
325
+ company_id=company_id,
326
+ metadataFilter={
327
+ "or": [
328
+ {
329
+ "and": [
330
+ {
331
+ "operator": "contains",
332
+ "path": [
333
+ "folderIdPath"
334
+ ],
335
+ "value": "uniquepathid://scope_abcdibgznc4bkdcx120zm5d"
336
+ },
337
+ {
338
+ "operator": "contains",
339
+ "path": [
340
+ "title"
341
+ ],
342
+ "value": "ai"
343
+ }
344
+ ]
345
+ }
346
+ ]
347
+ },
348
+ skip=0,
349
+ take=3,
350
+ )
351
+ ```
352
+
285
353
  #### `unique_sdk.Content.upsert`
286
354
 
287
355
  Enables upload of a new Content into the Knowledge base of unique into a specific scope with `scopeId` or a specific `chatId`. One of the two must be set.
@@ -297,6 +365,14 @@ createdContent = upload_file(
297
365
  "test.pdf",
298
366
  "application/pdf",
299
367
  "scope_stcj2osgbl722m22jayidx0n",
368
+ ingestionConfig={
369
+ "chunkMaxTokens": 1000,
370
+ "chunkStrategy": "default",
371
+ "uniqueIngestionMode": "standard",
372
+ },
373
+ metadata={
374
+ "folderIdPath": "uniquepathid://scope_id"
375
+ }
300
376
  )
301
377
 
302
378
  def upload_file(
@@ -306,6 +382,8 @@ def upload_file(
306
382
  displayed_filename,
307
383
  mimeType,
308
384
  scope_or_unique_path,
385
+ ingestion_config=None,
386
+ metadata=None,
309
387
  ):
310
388
  size = os.path.getsize(path_to_file)
311
389
  createdContent = unique_sdk.Content.upsert(
@@ -315,6 +393,8 @@ def upload_file(
315
393
  "key": displayed_filename,
316
394
  "title": displayed_filename,
317
395
  "mimeType": mimeType,
396
+ "ingestionConfig": ingestionConfig,
397
+ "metadata": metadata,
318
398
  },
319
399
  scopeId=scope_or_unique_path,
320
400
  )
@@ -340,6 +420,8 @@ def upload_file(
340
420
  "title": displayed_filename,
341
421
  "mimeType": mimeType,
342
422
  "byteSize": size,
423
+ "ingestionConfig": ingestionConfig,
424
+ "metadata": metadata,
343
425
  },
344
426
  scopeId=scope_or_unique_path,
345
427
  readUrl=createdContent.readUrl,
@@ -544,6 +626,7 @@ These are the options are available for `searchType`:
544
626
  `scopeIds` Specifies a collection of scope IDs to confine the search.
545
627
  `language` Optional. The language specification for full text search.
546
628
  `reranker` Optional. The reranker service to be used for re-ranking the search results.
629
+ `chatId` Optional, adds the documents uploaded in this chat to the scope of searched documents.
547
630
 
548
631
  ```python
549
632
  search = unique_sdk.Search.create(
@@ -715,7 +798,7 @@ A metadata filter such as the one designed above can be used in a `Search.create
715
798
 
716
799
  ### Chat History
717
800
 
718
- #### `unique_sdk.util.chat_history.load_history`
801
+ #### `unique_sdk.utils.chat_history.load_history`
719
802
 
720
803
  A helper function that makes sure the chat history is fully loaded and cut to the size of the token window that it fits into the next round of chat interactions.
721
804
 
@@ -733,7 +816,7 @@ history = unique_sdk.utils.chat_history.load_history(
733
816
  )
734
817
  ```
735
818
 
736
- #### `unique_sdk.util.chat_history.convert_chat_history_to_injectable_string`
819
+ #### `unique_sdk.utils.chat_history.convert_chat_history_to_injectable_string`
737
820
 
738
821
  convert history into a string that can be injected into a prompt. it als returns the token length of the converted history.
739
822
 
@@ -747,7 +830,7 @@ chat_history-string, chat_context_token_length = unique_sdk.utils.chat_history.c
747
830
 
748
831
  Interacting with the knowledge-base.
749
832
 
750
- #### `unique_sdk.util.file_io.download_content`
833
+ #### `unique_sdk.utils.file_io.download_content`
751
834
 
752
835
  download files and save them into a folder in `/tmp`
753
836
 
@@ -763,7 +846,7 @@ pdfFile = download_content(
763
846
  }
764
847
  ```
765
848
 
766
- #### `unique_sdk.util.file_io.upload_file`
849
+ #### `unique_sdk.utils.file_io.upload_file`
767
850
 
768
851
  Allows for uploading files that then get ingested in a scope or a chat.
769
852
 
@@ -773,15 +856,15 @@ createdContent = upload_file(
773
856
  userId=userId,
774
857
  path_to_file="/tmp/hello.pdf",
775
858
  displayed_filename="hello.pdf",
776
- mimeType="application/pdf",
777
- uploadScope="scope_stcj2osgbl722m22jayidx0n",
859
+ mime_type="application/pdf",
860
+ scope_or_unique_path="scope_stcj2osgbl722m22jayidx0n",
778
861
  chat_id=None,
779
862
  )
780
863
  ```
781
864
 
782
865
  ### Sources
783
866
 
784
- #### `unique_sdk.util.sources.merge_sources`
867
+ #### `unique_sdk.utils.sources.merge_sources`
785
868
 
786
869
  Merges multiple search results based on their 'id', removing redundant document and info markers.
787
870
 
@@ -810,15 +893,15 @@ search = unique_sdk.Search.create(
810
893
  chatOnly=False,
811
894
  )
812
895
 
813
- searchContext = unique_sdk.util.token.pick_search_results_for_token_window(
896
+ searchContext = unique_sdk.utils.token.pick_search_results_for_token_window(
814
897
  search["data"], config["maxTokens"] - historyLength
815
898
  )
816
899
 
817
- searchContext = unique_sdk.util.sources.merge_sources(search)
900
+ searchContext = unique_sdk.utils.sources.merge_sources(search)
818
901
 
819
902
  ```
820
903
 
821
- #### `unique_sdk.util.sources.sort_sources`
904
+ #### `unique_sdk.utils.sources.sort_sources`
822
905
 
823
906
  Sort sources by order of appearance in documents
824
907
 
@@ -835,14 +918,14 @@ search = unique_sdk.Search.create(
835
918
  chatOnly=False,
836
919
  )
837
920
 
838
- searchContext = unique_sdk.util.token.pick_search_results_for_token_window(
921
+ searchContext = unique_sdk.utils.token.pick_search_results_for_token_window(
839
922
  search["data"], config["maxTokens"] - historyLength
840
923
  )
841
924
 
842
- searchContext = unique_sdk.util.sources.sort_sources(search)
925
+ searchContext = unique_sdk.utils.sources.sort_sources(search)
843
926
  ```
844
927
 
845
- #### `unique_sdk.util.sources.post_process_sources`
928
+ #### `unique_sdk.utils.sources.post_process_sources`
846
929
 
847
930
  Post-processes the provided text by converting source references into superscript numerals (required
848
931
  format by backend to display sources in the chat window)
@@ -869,7 +952,7 @@ text_with_sup = post_process_sources(text)
869
952
 
870
953
  ### Token
871
954
 
872
- #### unique_sdk.util.token.pick_search_results_for_token_window
955
+ #### unique_sdk.utils.token.pick_search_results_for_token_window
873
956
 
874
957
  Selects and returns a list of search results that fit within a specified token limit.
875
958
 
@@ -898,12 +981,12 @@ search = unique_sdk.Search.create(
898
981
  chatOnly=False,
899
982
  )
900
983
 
901
- searchContext = unique_sdk.util.token.pick_search_results_for_token_window(
984
+ searchContext = unique_sdk.utils.token.pick_search_results_for_token_window(
902
985
  search["data"], config["maxTokens"] - historyLength
903
986
  )
904
987
  ```
905
988
 
906
- #### unique_sdk.util.token.count_tokens
989
+ #### unique_sdk.utils.token.count_tokens
907
990
 
908
991
  Counts the number of tokens in the provided text.
909
992
 
@@ -920,7 +1003,7 @@ Returns:
920
1003
 
921
1004
  ```python
922
1005
  hello = "hello you!"
923
- searchContext = unique_sdk.util.token.count_tokens(hello)
1006
+ searchContext = unique_sdk.utils.token.count_tokens(hello)
924
1007
  ```
925
1008
 
926
1009
  ## Error Handling
@@ -940,6 +1023,20 @@ All notable changes to this project will be documented in this file.
940
1023
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
941
1024
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
942
1025
 
1026
+ ## [0.9.28] - 2025-05-20
1027
+ - Add function to search content info. This also allows filtering content info by metadata info.
1028
+
1029
+ ## [0.9.27] - 2025-05-14
1030
+ - Add the possibility to specify metadata when creating or updating a Content.
1031
+
1032
+ ## [0.9.26] - 2025-05-13
1033
+ - Add the possibility to specify ingestionConfig when creating or updating a Content.
1034
+
1035
+ ## [0.9.25] - 2025-05-02
1036
+ - Fixed typos in `README.md`, including incorrect `sdk.utils` imports and code example errors.
1037
+
1038
+ ## [0.9.24] - 2025-04-23
1039
+ - Make `chatId` property in `Search.CreateParams` optional
943
1040
 
944
1041
  ## [0.9.23] - 2025-03-25
945
1042
  - Define programming language classifier explicitly for python 3.11
@@ -267,6 +267,73 @@ unique_sdk.Content.search(
267
267
  )
268
268
  ```
269
269
 
270
+ #### `unique_sdk.Content.get_info`
271
+
272
+ Allows you to get content info. To filter the results you can define a metadata filter in UniqueQL language. Find out more about it in the UniqueQL section. An example of a metadata filter defined with UniqueQL is the following:
273
+
274
+ ```python
275
+ metadataFilter: {
276
+ "or": [
277
+ {
278
+ "and": [
279
+ {
280
+ "operator": "contains",
281
+ "path": [
282
+ "folderIdPath"
283
+ ],
284
+ "value": "uniquepathid://test_id"
285
+ },
286
+ {
287
+ "operator": "contains",
288
+ "path": [
289
+ "title"
290
+ ],
291
+ "value": "ai"
292
+ }
293
+ ]
294
+ }
295
+ ]
296
+ },
297
+ ```
298
+
299
+ Pagination is also enabled for this functionality, and the default number of returned results is 50 with no entries skipped. Use the following paramteres to get the desired page:`
300
+
301
+ - `skip`
302
+ - `take`
303
+
304
+ Here is an example of retrieving the first 3 content infos that contain the value `uniquepathid://scope_abcdibgznc4bkdcx120zm5d` in the `folderIdPath` metadata and the value `ai` for the `tile` metadata.
305
+
306
+ ```python
307
+ content_info_result = unique_sdk.Content.get_info(
308
+ user_id=user_id,
309
+ company_id=company_id,
310
+ metadataFilter={
311
+ "or": [
312
+ {
313
+ "and": [
314
+ {
315
+ "operator": "contains",
316
+ "path": [
317
+ "folderIdPath"
318
+ ],
319
+ "value": "uniquepathid://scope_abcdibgznc4bkdcx120zm5d"
320
+ },
321
+ {
322
+ "operator": "contains",
323
+ "path": [
324
+ "title"
325
+ ],
326
+ "value": "ai"
327
+ }
328
+ ]
329
+ }
330
+ ]
331
+ },
332
+ skip=0,
333
+ take=3,
334
+ )
335
+ ```
336
+
270
337
  #### `unique_sdk.Content.upsert`
271
338
 
272
339
  Enables upload of a new Content into the Knowledge base of unique into a specific scope with `scopeId` or a specific `chatId`. One of the two must be set.
@@ -282,6 +349,14 @@ createdContent = upload_file(
282
349
  "test.pdf",
283
350
  "application/pdf",
284
351
  "scope_stcj2osgbl722m22jayidx0n",
352
+ ingestionConfig={
353
+ "chunkMaxTokens": 1000,
354
+ "chunkStrategy": "default",
355
+ "uniqueIngestionMode": "standard",
356
+ },
357
+ metadata={
358
+ "folderIdPath": "uniquepathid://scope_id"
359
+ }
285
360
  )
286
361
 
287
362
  def upload_file(
@@ -291,6 +366,8 @@ def upload_file(
291
366
  displayed_filename,
292
367
  mimeType,
293
368
  scope_or_unique_path,
369
+ ingestion_config=None,
370
+ metadata=None,
294
371
  ):
295
372
  size = os.path.getsize(path_to_file)
296
373
  createdContent = unique_sdk.Content.upsert(
@@ -300,6 +377,8 @@ def upload_file(
300
377
  "key": displayed_filename,
301
378
  "title": displayed_filename,
302
379
  "mimeType": mimeType,
380
+ "ingestionConfig": ingestionConfig,
381
+ "metadata": metadata,
303
382
  },
304
383
  scopeId=scope_or_unique_path,
305
384
  )
@@ -325,6 +404,8 @@ def upload_file(
325
404
  "title": displayed_filename,
326
405
  "mimeType": mimeType,
327
406
  "byteSize": size,
407
+ "ingestionConfig": ingestionConfig,
408
+ "metadata": metadata,
328
409
  },
329
410
  scopeId=scope_or_unique_path,
330
411
  readUrl=createdContent.readUrl,
@@ -529,6 +610,7 @@ These are the options are available for `searchType`:
529
610
  `scopeIds` Specifies a collection of scope IDs to confine the search.
530
611
  `language` Optional. The language specification for full text search.
531
612
  `reranker` Optional. The reranker service to be used for re-ranking the search results.
613
+ `chatId` Optional, adds the documents uploaded in this chat to the scope of searched documents.
532
614
 
533
615
  ```python
534
616
  search = unique_sdk.Search.create(
@@ -700,7 +782,7 @@ A metadata filter such as the one designed above can be used in a `Search.create
700
782
 
701
783
  ### Chat History
702
784
 
703
- #### `unique_sdk.util.chat_history.load_history`
785
+ #### `unique_sdk.utils.chat_history.load_history`
704
786
 
705
787
  A helper function that makes sure the chat history is fully loaded and cut to the size of the token window that it fits into the next round of chat interactions.
706
788
 
@@ -718,7 +800,7 @@ history = unique_sdk.utils.chat_history.load_history(
718
800
  )
719
801
  ```
720
802
 
721
- #### `unique_sdk.util.chat_history.convert_chat_history_to_injectable_string`
803
+ #### `unique_sdk.utils.chat_history.convert_chat_history_to_injectable_string`
722
804
 
723
805
  convert history into a string that can be injected into a prompt. it als returns the token length of the converted history.
724
806
 
@@ -732,7 +814,7 @@ chat_history-string, chat_context_token_length = unique_sdk.utils.chat_history.c
732
814
 
733
815
  Interacting with the knowledge-base.
734
816
 
735
- #### `unique_sdk.util.file_io.download_content`
817
+ #### `unique_sdk.utils.file_io.download_content`
736
818
 
737
819
  download files and save them into a folder in `/tmp`
738
820
 
@@ -748,7 +830,7 @@ pdfFile = download_content(
748
830
  }
749
831
  ```
750
832
 
751
- #### `unique_sdk.util.file_io.upload_file`
833
+ #### `unique_sdk.utils.file_io.upload_file`
752
834
 
753
835
  Allows for uploading files that then get ingested in a scope or a chat.
754
836
 
@@ -758,15 +840,15 @@ createdContent = upload_file(
758
840
  userId=userId,
759
841
  path_to_file="/tmp/hello.pdf",
760
842
  displayed_filename="hello.pdf",
761
- mimeType="application/pdf",
762
- uploadScope="scope_stcj2osgbl722m22jayidx0n",
843
+ mime_type="application/pdf",
844
+ scope_or_unique_path="scope_stcj2osgbl722m22jayidx0n",
763
845
  chat_id=None,
764
846
  )
765
847
  ```
766
848
 
767
849
  ### Sources
768
850
 
769
- #### `unique_sdk.util.sources.merge_sources`
851
+ #### `unique_sdk.utils.sources.merge_sources`
770
852
 
771
853
  Merges multiple search results based on their 'id', removing redundant document and info markers.
772
854
 
@@ -795,15 +877,15 @@ search = unique_sdk.Search.create(
795
877
  chatOnly=False,
796
878
  )
797
879
 
798
- searchContext = unique_sdk.util.token.pick_search_results_for_token_window(
880
+ searchContext = unique_sdk.utils.token.pick_search_results_for_token_window(
799
881
  search["data"], config["maxTokens"] - historyLength
800
882
  )
801
883
 
802
- searchContext = unique_sdk.util.sources.merge_sources(search)
884
+ searchContext = unique_sdk.utils.sources.merge_sources(search)
803
885
 
804
886
  ```
805
887
 
806
- #### `unique_sdk.util.sources.sort_sources`
888
+ #### `unique_sdk.utils.sources.sort_sources`
807
889
 
808
890
  Sort sources by order of appearance in documents
809
891
 
@@ -820,14 +902,14 @@ search = unique_sdk.Search.create(
820
902
  chatOnly=False,
821
903
  )
822
904
 
823
- searchContext = unique_sdk.util.token.pick_search_results_for_token_window(
905
+ searchContext = unique_sdk.utils.token.pick_search_results_for_token_window(
824
906
  search["data"], config["maxTokens"] - historyLength
825
907
  )
826
908
 
827
- searchContext = unique_sdk.util.sources.sort_sources(search)
909
+ searchContext = unique_sdk.utils.sources.sort_sources(search)
828
910
  ```
829
911
 
830
- #### `unique_sdk.util.sources.post_process_sources`
912
+ #### `unique_sdk.utils.sources.post_process_sources`
831
913
 
832
914
  Post-processes the provided text by converting source references into superscript numerals (required
833
915
  format by backend to display sources in the chat window)
@@ -854,7 +936,7 @@ text_with_sup = post_process_sources(text)
854
936
 
855
937
  ### Token
856
938
 
857
- #### unique_sdk.util.token.pick_search_results_for_token_window
939
+ #### unique_sdk.utils.token.pick_search_results_for_token_window
858
940
 
859
941
  Selects and returns a list of search results that fit within a specified token limit.
860
942
 
@@ -883,12 +965,12 @@ search = unique_sdk.Search.create(
883
965
  chatOnly=False,
884
966
  )
885
967
 
886
- searchContext = unique_sdk.util.token.pick_search_results_for_token_window(
968
+ searchContext = unique_sdk.utils.token.pick_search_results_for_token_window(
887
969
  search["data"], config["maxTokens"] - historyLength
888
970
  )
889
971
  ```
890
972
 
891
- #### unique_sdk.util.token.count_tokens
973
+ #### unique_sdk.utils.token.count_tokens
892
974
 
893
975
  Counts the number of tokens in the provided text.
894
976
 
@@ -905,7 +987,7 @@ Returns:
905
987
 
906
988
  ```python
907
989
  hello = "hello you!"
908
- searchContext = unique_sdk.util.token.count_tokens(hello)
990
+ searchContext = unique_sdk.utils.token.count_tokens(hello)
909
991
  ```
910
992
 
911
993
  ## Error Handling
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_sdk"
3
- version = "0.9.23"
3
+ version = "0.9.28"
4
4
  description = ""
5
5
  authors = [
6
6
  "Martin Fadler <martin.fadler@unique.ch>",
@@ -16,6 +16,7 @@ classifiers = [
16
16
  [tool.poetry.dependencies]
17
17
  python = "^3.11"
18
18
  typing-extensions = "^4.9.0"
19
+ requests = "^2.32.3"
19
20
 
20
21
 
21
22
  [tool.poetry.group.dev.dependencies]
@@ -25,6 +26,7 @@ tox = "^4.11.4"
25
26
  pyright = "^1.1.341"
26
27
  pytest-cov = "^4.1.0"
27
28
  pytest-asyncio = "^0.24.0"
29
+ python-dotenv = "^1.1.0"
28
30
 
29
31
  [build-system]
30
32
  requires = ["poetry-core"]
@@ -65,8 +65,38 @@ class Content(APIResource["Content"]):
65
65
  where: "Content.ContentWhereInput"
66
66
  chatId: NotRequired[str]
67
67
 
68
- class IngestionConfig(TypedDict):
68
+ class ContentInfoParams(TypedDict):
69
+ """
70
+ Parameters for the content info endpoint.
71
+ This is used to retrieve information about content based on various filters.
72
+ """
73
+
74
+ metadataFilter: dict
75
+ skip: int | None
76
+ take: int | None
77
+
78
+ class CustomApiOptions(TypedDict):
79
+ apiIdentifier: str
80
+ apiPayload: Optional[str]
81
+ customisationType: str
82
+
83
+ class VttConfig(TypedDict, total=False):
84
+ languageModel: Optional[str]
85
+
86
+ class IngestionConfig(TypedDict, total=False):
87
+ chunkMaxTokens: Optional[int]
88
+ chunkMaxTokensOnePager: Optional[int]
89
+ chunkMinTokens: Optional[int]
90
+ chunkStrategy: Optional[str]
91
+ customApiOptions: Optional[List["Content.CustomApiOptions"]]
92
+ documentMinTokens: Optional[int]
93
+ excelReadMode: Optional[str]
94
+ jpgReadMode: Optional[str]
95
+ pdfReadMode: Optional[str]
96
+ pptReadMode: Optional[str]
69
97
  uniqueIngestionMode: str
98
+ vttConfig: Optional["Content.VttConfig"]
99
+ wordReadMode: Optional[str]
70
100
 
71
101
  class Input(TypedDict):
72
102
  key: str
@@ -76,6 +106,7 @@ class Content(APIResource["Content"]):
76
106
  ownerId: str
77
107
  byteSize: Optional[int]
78
108
  ingestionConfig: "Content.IngestionConfig"
109
+ metadata: dict[str, any] | None = None
79
110
 
80
111
  class UpsertParams(RequestOptions):
81
112
  input: "Content.Input"
@@ -92,6 +123,30 @@ class Content(APIResource["Content"]):
92
123
  endPage: Optional[int]
93
124
  order: Optional[int]
94
125
 
126
+ class ContentInfo(TypedDict):
127
+ """
128
+ Partial representation of the content containing only the base information.
129
+ This is used for the content info endpoint.
130
+ """
131
+
132
+ id: str
133
+ key: str
134
+ url: str | None
135
+ title: str | None
136
+ metadata: Dict[str, Any] | None
137
+ mimeType: str
138
+ byteSize: int
139
+ ownerId: str
140
+ createdAt: str
141
+ updatedAt: str
142
+ expiresAt: str | None
143
+ deletedAt: str | None
144
+ expiredAt: str | None
145
+
146
+ class PaginatedContentInfo(TypedDict):
147
+ contentInfo: List["Content.ContentInfo"]
148
+ totalCount: int
149
+
95
150
  id: str
96
151
  key: str
97
152
  url: Optional[str]
@@ -136,6 +191,42 @@ class Content(APIResource["Content"]):
136
191
  ),
137
192
  )
138
193
 
194
+ @classmethod
195
+ def get_info(
196
+ cls,
197
+ user_id: str,
198
+ company_id: str,
199
+ **params: Unpack["Content.ContentInfoParams"],
200
+ ) -> PaginatedContentInfo:
201
+ return cast(
202
+ Content.PaginatedContentInfo,
203
+ cls._static_request(
204
+ "post",
205
+ "/content/info",
206
+ user_id,
207
+ company_id,
208
+ params=params,
209
+ ),
210
+ )
211
+
212
+ @classmethod
213
+ async def get_info_async(
214
+ cls,
215
+ user_id: str,
216
+ company_id: str,
217
+ **params: Unpack["Content.ContentInfoParams"],
218
+ ) -> PaginatedContentInfo:
219
+ return cast(
220
+ Content.PaginatedContentInfo,
221
+ await cls._static_request_async(
222
+ "post",
223
+ "/content/info",
224
+ user_id,
225
+ company_id,
226
+ params=params,
227
+ ),
228
+ )
229
+
139
230
  @classmethod
140
231
  def upsert(
141
232
  cls,
@@ -8,7 +8,7 @@ class Search(APIResource["Search"]):
8
8
  OBJECT_NAME: ClassVar[Literal["search.search"]] = "search.search"
9
9
 
10
10
  class CreateParams(RequestOptions):
11
- chatId: str
11
+ chatId: NotRequired[Optional[str]]
12
12
  searchString: str
13
13
  searchType: Literal["VECTOR", "COMBINED"]
14
14
  language: NotRequired[Optional[str]]
@@ -1,10 +1,12 @@
1
1
  import os
2
2
  import tempfile
3
3
  from pathlib import Path
4
+ from typing import Optional
4
5
 
5
6
  import requests
6
7
 
7
8
  import unique_sdk
9
+ from unique_sdk.api_resources._content import Content
8
10
 
9
11
 
10
12
  # download readUrl a random directory in /tmp
@@ -38,19 +40,23 @@ def upload_file(
38
40
  mime_type,
39
41
  scope_or_unique_path=None,
40
42
  chat_id=None,
43
+ ingestion_config: Optional[Content.IngestionConfig] = None,
44
+ metadata: dict[str, any] | None = None,
41
45
  ):
42
46
  # check that chatid or scope_or_unique_path is provided
43
47
  if not chat_id and not scope_or_unique_path:
44
48
  raise ValueError("chat_id or scope_or_unique_path must be provided")
45
49
 
46
50
  size = os.path.getsize(path_to_file)
47
- createdContent = unique_sdk.Content.upsert(
51
+ createdContent = Content.upsert(
48
52
  user_id=userId,
49
53
  company_id=companyId,
50
54
  input={
51
55
  "key": displayed_filename,
52
56
  "title": displayed_filename,
53
57
  "mimeType": mime_type,
58
+ "ingestionConfig": ingestion_config,
59
+ "metadata": metadata,
54
60
  },
55
61
  scopeId=scope_or_unique_path,
56
62
  chatId=chat_id,
@@ -78,6 +84,8 @@ def upload_file(
78
84
  "title": displayed_filename,
79
85
  "mimeType": mime_type,
80
86
  "byteSize": size,
87
+ "ingestionConfig": ingestion_config,
88
+ "metadata": metadata,
81
89
  },
82
90
  fileUrl=createdContent.readUrl,
83
91
  chatId=chat_id,
@@ -91,6 +99,8 @@ def upload_file(
91
99
  "title": displayed_filename,
92
100
  "mimeType": mime_type,
93
101
  "byteSize": size,
102
+ "ingestionConfig": ingestion_config,
103
+ "metadata": metadata,
94
104
  },
95
105
  fileUrl=createdContent.readUrl,
96
106
  scopeId=scope_or_unique_path,
File without changes