isaacus 0.3.3__tar.gz → 0.4.0__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 (75) hide show
  1. isaacus-0.4.0/.release-please-manifest.json +3 -0
  2. {isaacus-0.3.3 → isaacus-0.4.0}/CHANGELOG.md +18 -0
  3. {isaacus-0.3.3 → isaacus-0.4.0}/PKG-INFO +12 -12
  4. {isaacus-0.3.3 → isaacus-0.4.0}/README.md +11 -11
  5. {isaacus-0.3.3 → isaacus-0.4.0}/pyproject.toml +2 -2
  6. {isaacus-0.3.3 → isaacus-0.4.0}/requirements-dev.lock +1 -1
  7. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_base_client.py +5 -1
  8. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_models.py +0 -1
  9. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_typing.py +1 -1
  10. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_version.py +1 -1
  11. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/resources/classifications/universal.py +23 -23
  12. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/types/classifications/universal_classification.py +36 -12
  13. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/types/classifications/universal_create_params.py +10 -10
  14. {isaacus-0.3.3 → isaacus-0.4.0}/tests/api_resources/classifications/test_universal.py +8 -8
  15. {isaacus-0.3.3 → isaacus-0.4.0}/tests/conftest.py +1 -1
  16. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_client.py +10 -10
  17. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_models.py +4 -1
  18. isaacus-0.3.3/.release-please-manifest.json +0 -3
  19. {isaacus-0.3.3 → isaacus-0.4.0}/.gitignore +0 -0
  20. {isaacus-0.3.3 → isaacus-0.4.0}/CONTRIBUTING.md +0 -0
  21. {isaacus-0.3.3 → isaacus-0.4.0}/LICENSE +0 -0
  22. {isaacus-0.3.3 → isaacus-0.4.0}/SECURITY.md +0 -0
  23. {isaacus-0.3.3 → isaacus-0.4.0}/api.md +0 -0
  24. {isaacus-0.3.3 → isaacus-0.4.0}/bin/check-release-environment +0 -0
  25. {isaacus-0.3.3 → isaacus-0.4.0}/bin/publish-pypi +0 -0
  26. {isaacus-0.3.3 → isaacus-0.4.0}/examples/.keep +0 -0
  27. {isaacus-0.3.3 → isaacus-0.4.0}/mypy.ini +0 -0
  28. {isaacus-0.3.3 → isaacus-0.4.0}/noxfile.py +0 -0
  29. {isaacus-0.3.3 → isaacus-0.4.0}/release-please-config.json +0 -0
  30. {isaacus-0.3.3 → isaacus-0.4.0}/requirements.lock +0 -0
  31. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/__init__.py +0 -0
  32. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_client.py +0 -0
  33. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_compat.py +0 -0
  34. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_constants.py +0 -0
  35. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_exceptions.py +0 -0
  36. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_files.py +0 -0
  37. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_qs.py +0 -0
  38. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_resource.py +0 -0
  39. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_response.py +0 -0
  40. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_streaming.py +0 -0
  41. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_types.py +0 -0
  42. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/__init__.py +0 -0
  43. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_logs.py +0 -0
  44. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_proxy.py +0 -0
  45. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_reflection.py +0 -0
  46. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_streams.py +0 -0
  47. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_sync.py +0 -0
  48. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_transform.py +0 -0
  49. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/_utils/_utils.py +0 -0
  50. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/lib/.keep +0 -0
  51. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/py.typed +0 -0
  52. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/resources/__init__.py +0 -0
  53. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/resources/classifications/__init__.py +0 -0
  54. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/resources/classifications/classifications.py +0 -0
  55. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/resources/rerankings.py +0 -0
  56. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/types/__init__.py +0 -0
  57. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/types/classifications/__init__.py +0 -0
  58. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/types/reranking.py +0 -0
  59. {isaacus-0.3.3 → isaacus-0.4.0}/src/isaacus/types/reranking_create_params.py +0 -0
  60. {isaacus-0.3.3 → isaacus-0.4.0}/tests/__init__.py +0 -0
  61. {isaacus-0.3.3 → isaacus-0.4.0}/tests/api_resources/__init__.py +0 -0
  62. {isaacus-0.3.3 → isaacus-0.4.0}/tests/api_resources/classifications/__init__.py +0 -0
  63. {isaacus-0.3.3 → isaacus-0.4.0}/tests/api_resources/test_rerankings.py +0 -0
  64. {isaacus-0.3.3 → isaacus-0.4.0}/tests/sample_file.txt +0 -0
  65. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_deepcopy.py +0 -0
  66. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_extract_files.py +0 -0
  67. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_files.py +0 -0
  68. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_qs.py +0 -0
  69. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_required_args.py +0 -0
  70. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_response.py +0 -0
  71. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_streaming.py +0 -0
  72. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_transform.py +0 -0
  73. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_utils/test_proxy.py +0 -0
  74. {isaacus-0.3.3 → isaacus-0.4.0}/tests/test_utils/test_typing.py +0 -0
  75. {isaacus-0.3.3 → isaacus-0.4.0}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.4.0"
3
+ }
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (2025-04-19)
4
+
5
+ Full Changelog: [v0.3.3...v0.4.0](https://github.com/isaacus-dev/isaacus-python/compare/v0.3.3...v0.4.0)
6
+
7
+ ### ⚠ BREAKING CHANGES
8
+
9
+ * **api:** made universal classification endpoint multi-input only
10
+
11
+ ### Features
12
+
13
+ * **api:** made universal classification endpoint multi-input only ([4fb2535](https://github.com/isaacus-dev/isaacus-python/commit/4fb2535407d88d51c1db1e9a37c9ea767cdf06c0))
14
+
15
+
16
+ ### Chores
17
+
18
+ * **internal:** bump pyright version ([2f992e7](https://github.com/isaacus-dev/isaacus-python/commit/2f992e788860d16739438a021bd8825a7999b1e4))
19
+ * **internal:** update models test ([bb3df78](https://github.com/isaacus-dev/isaacus-python/commit/bb3df7823dd27e6482b5e97ef17019ee0a1e596c))
20
+
3
21
  ## 0.3.3 (2025-04-16)
4
22
 
5
23
  Full Changelog: [v0.3.2...v0.3.3](https://github.com/isaacus-dev/isaacus-python/compare/v0.3.2...v0.3.3)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: isaacus
3
- Version: 0.3.3
3
+ Version: 0.4.0
4
4
  Summary: The official Python library for the isaacus API
5
5
  Project-URL: Homepage, https://github.com/isaacus-dev/isaacus-python
6
6
  Project-URL: Repository, https://github.com/isaacus-dev/isaacus-python
@@ -65,9 +65,9 @@ client = Isaacus(
65
65
  universal_classification = client.classifications.universal.create(
66
66
  model="kanon-universal-classifier",
67
67
  query="This is a confidentiality clause.",
68
- text="I agree not to tell anyone about the document.",
68
+ texts=["I agree not to tell anyone about the document."],
69
69
  )
70
- print(universal_classification.chunks)
70
+ print(universal_classification.classifications)
71
71
  ```
72
72
 
73
73
  While you can provide an `api_key` keyword argument,
@@ -93,9 +93,9 @@ async def main() -> None:
93
93
  universal_classification = await client.classifications.universal.create(
94
94
  model="kanon-universal-classifier",
95
95
  query="This is a confidentiality clause.",
96
- text="I agree not to tell anyone about the document.",
96
+ texts=["I agree not to tell anyone about the document."],
97
97
  )
98
- print(universal_classification.chunks)
98
+ print(universal_classification.classifications)
99
99
 
100
100
 
101
101
  asyncio.run(main())
@@ -124,7 +124,7 @@ client = Isaacus()
124
124
  universal_classification = client.classifications.universal.create(
125
125
  model="kanon-universal-classifier",
126
126
  query="This is a confidentiality clause.",
127
- text="I agree not to tell anyone about the document.",
127
+ texts=["I agree not to tell anyone about the document."],
128
128
  chunking_options={
129
129
  "overlap_ratio": 0.1,
130
130
  "overlap_tokens": None,
@@ -153,7 +153,7 @@ try:
153
153
  client.classifications.universal.create(
154
154
  model="kanon-universal-classifier",
155
155
  query="This is a confidentiality clause.",
156
- text="I agree not to tell anyone about the document.",
156
+ texts=["I agree not to tell anyone about the document."],
157
157
  )
158
158
  except isaacus.APIConnectionError as e:
159
159
  print("The server could not be reached")
@@ -200,7 +200,7 @@ client = Isaacus(
200
200
  client.with_options(max_retries=5).classifications.universal.create(
201
201
  model="kanon-universal-classifier",
202
202
  query="This is a confidentiality clause.",
203
- text="I agree not to tell anyone about the document.",
203
+ texts=["I agree not to tell anyone about the document."],
204
204
  )
205
205
  ```
206
206
 
@@ -227,7 +227,7 @@ client = Isaacus(
227
227
  client.with_options(timeout=5.0).classifications.universal.create(
228
228
  model="kanon-universal-classifier",
229
229
  query="This is a confidentiality clause.",
230
- text="I agree not to tell anyone about the document.",
230
+ texts=["I agree not to tell anyone about the document."],
231
231
  )
232
232
  ```
233
233
 
@@ -272,12 +272,12 @@ client = Isaacus()
272
272
  response = client.classifications.universal.with_raw_response.create(
273
273
  model="kanon-universal-classifier",
274
274
  query="This is a confidentiality clause.",
275
- text="I agree not to tell anyone about the document.",
275
+ texts=["I agree not to tell anyone about the document."],
276
276
  )
277
277
  print(response.headers.get('X-My-Header'))
278
278
 
279
279
  universal = response.parse() # get the object that `classifications.universal.create()` would have returned
280
- print(universal.chunks)
280
+ print(universal.classifications)
281
281
  ```
282
282
 
283
283
  These methods return an [`APIResponse`](https://github.com/isaacus-dev/isaacus-python/tree/main/src/isaacus/_response.py) object.
@@ -294,7 +294,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi
294
294
  with client.classifications.universal.with_streaming_response.create(
295
295
  model="kanon-universal-classifier",
296
296
  query="This is a confidentiality clause.",
297
- text="I agree not to tell anyone about the document.",
297
+ texts=["I agree not to tell anyone about the document."],
298
298
  ) as response:
299
299
  print(response.headers.get("X-My-Header"))
300
300
 
@@ -34,9 +34,9 @@ client = Isaacus(
34
34
  universal_classification = client.classifications.universal.create(
35
35
  model="kanon-universal-classifier",
36
36
  query="This is a confidentiality clause.",
37
- text="I agree not to tell anyone about the document.",
37
+ texts=["I agree not to tell anyone about the document."],
38
38
  )
39
- print(universal_classification.chunks)
39
+ print(universal_classification.classifications)
40
40
  ```
41
41
 
42
42
  While you can provide an `api_key` keyword argument,
@@ -62,9 +62,9 @@ async def main() -> None:
62
62
  universal_classification = await client.classifications.universal.create(
63
63
  model="kanon-universal-classifier",
64
64
  query="This is a confidentiality clause.",
65
- text="I agree not to tell anyone about the document.",
65
+ texts=["I agree not to tell anyone about the document."],
66
66
  )
67
- print(universal_classification.chunks)
67
+ print(universal_classification.classifications)
68
68
 
69
69
 
70
70
  asyncio.run(main())
@@ -93,7 +93,7 @@ client = Isaacus()
93
93
  universal_classification = client.classifications.universal.create(
94
94
  model="kanon-universal-classifier",
95
95
  query="This is a confidentiality clause.",
96
- text="I agree not to tell anyone about the document.",
96
+ texts=["I agree not to tell anyone about the document."],
97
97
  chunking_options={
98
98
  "overlap_ratio": 0.1,
99
99
  "overlap_tokens": None,
@@ -122,7 +122,7 @@ try:
122
122
  client.classifications.universal.create(
123
123
  model="kanon-universal-classifier",
124
124
  query="This is a confidentiality clause.",
125
- text="I agree not to tell anyone about the document.",
125
+ texts=["I agree not to tell anyone about the document."],
126
126
  )
127
127
  except isaacus.APIConnectionError as e:
128
128
  print("The server could not be reached")
@@ -169,7 +169,7 @@ client = Isaacus(
169
169
  client.with_options(max_retries=5).classifications.universal.create(
170
170
  model="kanon-universal-classifier",
171
171
  query="This is a confidentiality clause.",
172
- text="I agree not to tell anyone about the document.",
172
+ texts=["I agree not to tell anyone about the document."],
173
173
  )
174
174
  ```
175
175
 
@@ -196,7 +196,7 @@ client = Isaacus(
196
196
  client.with_options(timeout=5.0).classifications.universal.create(
197
197
  model="kanon-universal-classifier",
198
198
  query="This is a confidentiality clause.",
199
- text="I agree not to tell anyone about the document.",
199
+ texts=["I agree not to tell anyone about the document."],
200
200
  )
201
201
  ```
202
202
 
@@ -241,12 +241,12 @@ client = Isaacus()
241
241
  response = client.classifications.universal.with_raw_response.create(
242
242
  model="kanon-universal-classifier",
243
243
  query="This is a confidentiality clause.",
244
- text="I agree not to tell anyone about the document.",
244
+ texts=["I agree not to tell anyone about the document."],
245
245
  )
246
246
  print(response.headers.get('X-My-Header'))
247
247
 
248
248
  universal = response.parse() # get the object that `classifications.universal.create()` would have returned
249
- print(universal.chunks)
249
+ print(universal.classifications)
250
250
  ```
251
251
 
252
252
  These methods return an [`APIResponse`](https://github.com/isaacus-dev/isaacus-python/tree/main/src/isaacus/_response.py) object.
@@ -263,7 +263,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi
263
263
  with client.classifications.universal.with_streaming_response.create(
264
264
  model="kanon-universal-classifier",
265
265
  query="This is a confidentiality clause.",
266
- text="I agree not to tell anyone about the document.",
266
+ texts=["I agree not to tell anyone about the document."],
267
267
  ) as response:
268
268
  print(response.headers.get("X-My-Header"))
269
269
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "isaacus"
3
- version = "0.3.3"
3
+ version = "0.4.0"
4
4
  description = "The official Python library for the isaacus API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -42,7 +42,7 @@ Repository = "https://github.com/isaacus-dev/isaacus-python"
42
42
  managed = true
43
43
  # version pins are in requirements-dev.lock
44
44
  dev-dependencies = [
45
- "pyright>=1.1.359",
45
+ "pyright==1.1.399",
46
46
  "mypy",
47
47
  "respx",
48
48
  "pytest",
@@ -69,7 +69,7 @@ pydantic-core==2.27.1
69
69
  # via pydantic
70
70
  pygments==2.18.0
71
71
  # via rich
72
- pyright==1.1.392.post0
72
+ pyright==1.1.399
73
73
  pytest==8.3.3
74
74
  # via pytest-asyncio
75
75
  pytest-asyncio==0.24.0
@@ -98,7 +98,11 @@ _StreamT = TypeVar("_StreamT", bound=Stream[Any])
98
98
  _AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any])
99
99
 
100
100
  if TYPE_CHECKING:
101
- from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
101
+ from httpx._config import (
102
+ DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage]
103
+ )
104
+
105
+ HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG
102
106
  else:
103
107
  try:
104
108
  from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
@@ -19,7 +19,6 @@ from typing_extensions import (
19
19
  )
20
20
 
21
21
  import pydantic
22
- import pydantic.generics
23
22
  from pydantic.fields import FieldInfo
24
23
 
25
24
  from ._types import (
@@ -110,7 +110,7 @@ def extract_type_var_from_base(
110
110
  ```
111
111
  """
112
112
  cls = cast(object, get_origin(typ) or typ)
113
- if cls in generic_bases:
113
+ if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains]
114
114
  # we're given the class directly
115
115
  return extract_type_arg(typ, index)
116
116
 
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "isaacus"
4
- __version__ = "0.3.3" # x-release-please-version
4
+ __version__ = "0.4.0" # x-release-please-version
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Optional
5
+ from typing import List, Optional
6
6
  from typing_extensions import Literal
7
7
 
8
8
  import httpx
@@ -52,7 +52,7 @@ class UniversalResource(SyncAPIResource):
52
52
  *,
53
53
  model: Literal["kanon-universal-classifier", "kanon-universal-classifier-mini"],
54
54
  query: str,
55
- text: str,
55
+ texts: List[str],
56
56
  chunking_options: Optional[universal_create_params.ChunkingOptions] | NotGiven = NOT_GIVEN,
57
57
  is_iql: bool | NotGiven = NOT_GIVEN,
58
58
  scoring_method: Literal["auto", "chunk_max", "chunk_avg", "chunk_min"] | NotGiven = NOT_GIVEN,
@@ -64,7 +64,7 @@ class UniversalResource(SyncAPIResource):
64
64
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
65
65
  ) -> UniversalClassification:
66
66
  """
67
- Classify the relevance of a legal document to a query with an Isaacus universal
67
+ Classify the relevance of legal documents to a query with an Isaacus universal
68
68
  legal AI classifier.
69
69
 
70
70
  Args:
@@ -72,16 +72,16 @@ class UniversalResource(SyncAPIResource):
72
72
  to use for universal classification.
73
73
 
74
74
  query: The [Isaacus Query Language (IQL)](https://docs.isaacus.com/iql) query or, if
75
- IQL is disabled, the statement, to evaluate the text against.
75
+ IQL is disabled, the statement, to evaluate the texts against.
76
76
 
77
77
  The query must contain at least one non-whitespace character.
78
78
 
79
- Unlike the text being classified, the query cannot be so long that it exceeds
79
+ Unlike the texts being classified, the query cannot be so long that it exceeds
80
80
  the maximum input length of the universal classifier.
81
81
 
82
- text: The text to classify.
82
+ texts: The texts to classify.
83
83
 
84
- The text must contain at least one non-whitespace character.
84
+ The texts must contain at least one non-whitespace character.
85
85
 
86
86
  chunking_options: Options for how to split text into smaller chunks.
87
87
 
@@ -92,13 +92,13 @@ class UniversalResource(SyncAPIResource):
92
92
 
93
93
  `auto` is the default scoring method and is recommended for most use cases.
94
94
  Currently, it is equivalent to `chunk_max`. In the future, it will automatically
95
- select the best method based on the model and input.
95
+ select the best method based on the model and inputs.
96
96
 
97
- `chunk_max` uses the highest confidence score of all of the text's chunks.
97
+ `chunk_max` uses the highest confidence score of all of the texts' chunks.
98
98
 
99
- `chunk_avg` averages the confidence scores of all of the text's chunks.
99
+ `chunk_avg` averages the confidence scores of all of the texts' chunks.
100
100
 
101
- `chunk_min` uses the lowest confidence score of all of the text's chunks.
101
+ `chunk_min` uses the lowest confidence score of all of the texts' chunks.
102
102
 
103
103
  extra_headers: Send extra headers
104
104
 
@@ -114,7 +114,7 @@ class UniversalResource(SyncAPIResource):
114
114
  {
115
115
  "model": model,
116
116
  "query": query,
117
- "text": text,
117
+ "texts": texts,
118
118
  "chunking_options": chunking_options,
119
119
  "is_iql": is_iql,
120
120
  "scoring_method": scoring_method,
@@ -153,7 +153,7 @@ class AsyncUniversalResource(AsyncAPIResource):
153
153
  *,
154
154
  model: Literal["kanon-universal-classifier", "kanon-universal-classifier-mini"],
155
155
  query: str,
156
- text: str,
156
+ texts: List[str],
157
157
  chunking_options: Optional[universal_create_params.ChunkingOptions] | NotGiven = NOT_GIVEN,
158
158
  is_iql: bool | NotGiven = NOT_GIVEN,
159
159
  scoring_method: Literal["auto", "chunk_max", "chunk_avg", "chunk_min"] | NotGiven = NOT_GIVEN,
@@ -165,7 +165,7 @@ class AsyncUniversalResource(AsyncAPIResource):
165
165
  timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
166
166
  ) -> UniversalClassification:
167
167
  """
168
- Classify the relevance of a legal document to a query with an Isaacus universal
168
+ Classify the relevance of legal documents to a query with an Isaacus universal
169
169
  legal AI classifier.
170
170
 
171
171
  Args:
@@ -173,16 +173,16 @@ class AsyncUniversalResource(AsyncAPIResource):
173
173
  to use for universal classification.
174
174
 
175
175
  query: The [Isaacus Query Language (IQL)](https://docs.isaacus.com/iql) query or, if
176
- IQL is disabled, the statement, to evaluate the text against.
176
+ IQL is disabled, the statement, to evaluate the texts against.
177
177
 
178
178
  The query must contain at least one non-whitespace character.
179
179
 
180
- Unlike the text being classified, the query cannot be so long that it exceeds
180
+ Unlike the texts being classified, the query cannot be so long that it exceeds
181
181
  the maximum input length of the universal classifier.
182
182
 
183
- text: The text to classify.
183
+ texts: The texts to classify.
184
184
 
185
- The text must contain at least one non-whitespace character.
185
+ The texts must contain at least one non-whitespace character.
186
186
 
187
187
  chunking_options: Options for how to split text into smaller chunks.
188
188
 
@@ -193,13 +193,13 @@ class AsyncUniversalResource(AsyncAPIResource):
193
193
 
194
194
  `auto` is the default scoring method and is recommended for most use cases.
195
195
  Currently, it is equivalent to `chunk_max`. In the future, it will automatically
196
- select the best method based on the model and input.
196
+ select the best method based on the model and inputs.
197
197
 
198
- `chunk_max` uses the highest confidence score of all of the text's chunks.
198
+ `chunk_max` uses the highest confidence score of all of the texts' chunks.
199
199
 
200
- `chunk_avg` averages the confidence scores of all of the text's chunks.
200
+ `chunk_avg` averages the confidence scores of all of the texts' chunks.
201
201
 
202
- `chunk_min` uses the lowest confidence score of all of the text's chunks.
202
+ `chunk_min` uses the lowest confidence score of all of the texts' chunks.
203
203
 
204
204
  extra_headers: Send extra headers
205
205
 
@@ -215,7 +215,7 @@ class AsyncUniversalResource(AsyncAPIResource):
215
215
  {
216
216
  "model": model,
217
217
  "query": query,
218
- "text": text,
218
+ "texts": texts,
219
219
  "chunking_options": chunking_options,
220
220
  "is_iql": is_iql,
221
221
  "scoring_method": scoring_method,
@@ -4,15 +4,22 @@ from typing import List, Optional
4
4
 
5
5
  from ..._models import BaseModel
6
6
 
7
- __all__ = ["UniversalClassification", "Chunk", "Usage"]
7
+ __all__ = ["UniversalClassification", "Classification", "ClassificationChunk", "Usage"]
8
8
 
9
9
 
10
- class Chunk(BaseModel):
10
+ class ClassificationChunk(BaseModel):
11
11
  end: int
12
- """The end index of the chunk in the original text."""
12
+ """
13
+ The index of the character in the original text where the chunk ends, beginning
14
+ from `0` (such that, in Python, the chunk is equivalent to `text[start:end+1]`).
15
+ """
13
16
 
14
17
  index: int
15
- """The index of the chunk in the list of chunks."""
18
+ """
19
+ The original position of the chunk in the outputted list of chunks before
20
+ sorting, starting from `0` (and, therefore, ending at the number of chunks minus
21
+ `1`).
22
+ """
16
23
 
17
24
  score: float
18
25
  """
@@ -24,19 +31,17 @@ class Chunk(BaseModel):
24
31
  """
25
32
 
26
33
  start: int
27
- """The start index of the chunk in the original text."""
34
+ """
35
+ The index of the character in the original text where the chunk starts,
36
+ beginning from `0`.
37
+ """
28
38
 
29
39
  text: str
30
40
  """The text of the chunk."""
31
41
 
32
42
 
33
- class Usage(BaseModel):
34
- input_tokens: int
35
- """The number of tokens inputted to the model."""
36
-
37
-
38
- class UniversalClassification(BaseModel):
39
- chunks: Optional[List[Chunk]] = None
43
+ class Classification(BaseModel):
44
+ chunks: Optional[List[ClassificationChunk]] = None
40
45
  """
41
46
  The text as broken into chunks by
42
47
  [semchunk](https://github.com/isaacus-dev/semchunk), each chunk with its own
@@ -45,6 +50,12 @@ class UniversalClassification(BaseModel):
45
50
  If no chunking occurred, this will be `null`.
46
51
  """
47
52
 
53
+ index: int
54
+ """
55
+ The index of the text in the input array of texts, starting from `0` (and,
56
+ therefore, ending at the number of texts minus `1`).
57
+ """
58
+
48
59
  score: float
49
60
  """
50
61
  A score of the likelihood that the query expressed about the text is supported
@@ -54,5 +65,18 @@ class UniversalClassification(BaseModel):
54
65
  score less than `0.5` indicates that the text does not support the query.
55
66
  """
56
67
 
68
+
69
+ class Usage(BaseModel):
70
+ input_tokens: int
71
+ """The number of tokens inputted to the model."""
72
+
73
+
74
+ class UniversalClassification(BaseModel):
75
+ classifications: List[Classification]
76
+ """
77
+ The classifications of the texts, by relevance to the query, in order from
78
+ highest to lowest relevance score.
79
+ """
80
+
57
81
  usage: Usage
58
82
  """Statistics about the usage of resources in the process of classifying the text."""
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Optional
5
+ from typing import List, Optional
6
6
  from typing_extensions import Literal, Required, TypedDict
7
7
 
8
8
  __all__ = ["UniversalCreateParams", "ChunkingOptions"]
@@ -18,18 +18,18 @@ class UniversalCreateParams(TypedDict, total=False):
18
18
  query: Required[str]
19
19
  """
20
20
  The [Isaacus Query Language (IQL)](https://docs.isaacus.com/iql) query or, if
21
- IQL is disabled, the statement, to evaluate the text against.
21
+ IQL is disabled, the statement, to evaluate the texts against.
22
22
 
23
23
  The query must contain at least one non-whitespace character.
24
24
 
25
- Unlike the text being classified, the query cannot be so long that it exceeds
25
+ Unlike the texts being classified, the query cannot be so long that it exceeds
26
26
  the maximum input length of the universal classifier.
27
27
  """
28
28
 
29
- text: Required[str]
30
- """The text to classify.
29
+ texts: Required[List[str]]
30
+ """The texts to classify.
31
31
 
32
- The text must contain at least one non-whitespace character.
32
+ The texts must contain at least one non-whitespace character.
33
33
  """
34
34
 
35
35
  chunking_options: Optional[ChunkingOptions]
@@ -46,13 +46,13 @@ class UniversalCreateParams(TypedDict, total=False):
46
46
 
47
47
  `auto` is the default scoring method and is recommended for most use cases.
48
48
  Currently, it is equivalent to `chunk_max`. In the future, it will automatically
49
- select the best method based on the model and input.
49
+ select the best method based on the model and inputs.
50
50
 
51
- `chunk_max` uses the highest confidence score of all of the text's chunks.
51
+ `chunk_max` uses the highest confidence score of all of the texts' chunks.
52
52
 
53
- `chunk_avg` averages the confidence scores of all of the text's chunks.
53
+ `chunk_avg` averages the confidence scores of all of the texts' chunks.
54
54
 
55
- `chunk_min` uses the lowest confidence score of all of the text's chunks.
55
+ `chunk_min` uses the lowest confidence score of all of the texts' chunks.
56
56
  """
57
57
 
58
58
 
@@ -23,7 +23,7 @@ class TestUniversal:
23
23
  universal = client.classifications.universal.create(
24
24
  model="kanon-universal-classifier",
25
25
  query="This is a confidentiality clause.",
26
- text="I agree not to tell anyone about the document.",
26
+ texts=["I agree not to tell anyone about the document."],
27
27
  )
28
28
  assert_matches_type(UniversalClassification, universal, path=["response"])
29
29
 
@@ -33,7 +33,7 @@ class TestUniversal:
33
33
  universal = client.classifications.universal.create(
34
34
  model="kanon-universal-classifier",
35
35
  query="This is a confidentiality clause.",
36
- text="I agree not to tell anyone about the document.",
36
+ texts=["I agree not to tell anyone about the document."],
37
37
  chunking_options={
38
38
  "overlap_ratio": 0.1,
39
39
  "overlap_tokens": 0,
@@ -50,7 +50,7 @@ class TestUniversal:
50
50
  response = client.classifications.universal.with_raw_response.create(
51
51
  model="kanon-universal-classifier",
52
52
  query="This is a confidentiality clause.",
53
- text="I agree not to tell anyone about the document.",
53
+ texts=["I agree not to tell anyone about the document."],
54
54
  )
55
55
 
56
56
  assert response.is_closed is True
@@ -64,7 +64,7 @@ class TestUniversal:
64
64
  with client.classifications.universal.with_streaming_response.create(
65
65
  model="kanon-universal-classifier",
66
66
  query="This is a confidentiality clause.",
67
- text="I agree not to tell anyone about the document.",
67
+ texts=["I agree not to tell anyone about the document."],
68
68
  ) as response:
69
69
  assert not response.is_closed
70
70
  assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -84,7 +84,7 @@ class TestAsyncUniversal:
84
84
  universal = await async_client.classifications.universal.create(
85
85
  model="kanon-universal-classifier",
86
86
  query="This is a confidentiality clause.",
87
- text="I agree not to tell anyone about the document.",
87
+ texts=["I agree not to tell anyone about the document."],
88
88
  )
89
89
  assert_matches_type(UniversalClassification, universal, path=["response"])
90
90
 
@@ -94,7 +94,7 @@ class TestAsyncUniversal:
94
94
  universal = await async_client.classifications.universal.create(
95
95
  model="kanon-universal-classifier",
96
96
  query="This is a confidentiality clause.",
97
- text="I agree not to tell anyone about the document.",
97
+ texts=["I agree not to tell anyone about the document."],
98
98
  chunking_options={
99
99
  "overlap_ratio": 0.1,
100
100
  "overlap_tokens": 0,
@@ -111,7 +111,7 @@ class TestAsyncUniversal:
111
111
  response = await async_client.classifications.universal.with_raw_response.create(
112
112
  model="kanon-universal-classifier",
113
113
  query="This is a confidentiality clause.",
114
- text="I agree not to tell anyone about the document.",
114
+ texts=["I agree not to tell anyone about the document."],
115
115
  )
116
116
 
117
117
  assert response.is_closed is True
@@ -125,7 +125,7 @@ class TestAsyncUniversal:
125
125
  async with async_client.classifications.universal.with_streaming_response.create(
126
126
  model="kanon-universal-classifier",
127
127
  query="This is a confidentiality clause.",
128
- text="I agree not to tell anyone about the document.",
128
+ texts=["I agree not to tell anyone about the document."],
129
129
  ) as response:
130
130
  assert not response.is_closed
131
131
  assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -10,7 +10,7 @@ from pytest_asyncio import is_async_test
10
10
  from isaacus import Isaacus, AsyncIsaacus
11
11
 
12
12
  if TYPE_CHECKING:
13
- from _pytest.fixtures import FixtureRequest
13
+ from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage]
14
14
 
15
15
  pytest.register_assert_rewrite("tests.utils")
16
16
 
@@ -723,7 +723,7 @@ class TestIsaacus:
723
723
  dict(
724
724
  model="kanon-universal-classifier",
725
725
  query="This is a confidentiality clause.",
726
- text="I agree not to tell anyone about the document.",
726
+ texts=["I agree not to tell anyone about the document."],
727
727
  ),
728
728
  UniversalCreateParams,
729
729
  ),
@@ -748,7 +748,7 @@ class TestIsaacus:
748
748
  dict(
749
749
  model="kanon-universal-classifier",
750
750
  query="This is a confidentiality clause.",
751
- text="I agree not to tell anyone about the document.",
751
+ texts=["I agree not to tell anyone about the document."],
752
752
  ),
753
753
  UniversalCreateParams,
754
754
  ),
@@ -788,7 +788,7 @@ class TestIsaacus:
788
788
  response = client.classifications.universal.with_raw_response.create(
789
789
  model="kanon-universal-classifier",
790
790
  query="This is a confidentiality clause.",
791
- text="I agree not to tell anyone about the document.",
791
+ texts=["I agree not to tell anyone about the document."],
792
792
  )
793
793
 
794
794
  assert response.retries_taken == failures_before_success
@@ -816,7 +816,7 @@ class TestIsaacus:
816
816
  response = client.classifications.universal.with_raw_response.create(
817
817
  model="kanon-universal-classifier",
818
818
  query="This is a confidentiality clause.",
819
- text="I agree not to tell anyone about the document.",
819
+ texts=["I agree not to tell anyone about the document."],
820
820
  extra_headers={"x-stainless-retry-count": Omit()},
821
821
  )
822
822
 
@@ -844,7 +844,7 @@ class TestIsaacus:
844
844
  response = client.classifications.universal.with_raw_response.create(
845
845
  model="kanon-universal-classifier",
846
846
  query="This is a confidentiality clause.",
847
- text="I agree not to tell anyone about the document.",
847
+ texts=["I agree not to tell anyone about the document."],
848
848
  extra_headers={"x-stainless-retry-count": "42"},
849
849
  )
850
850
 
@@ -1533,7 +1533,7 @@ class TestAsyncIsaacus:
1533
1533
  dict(
1534
1534
  model="kanon-universal-classifier",
1535
1535
  query="This is a confidentiality clause.",
1536
- text="I agree not to tell anyone about the document.",
1536
+ texts=["I agree not to tell anyone about the document."],
1537
1537
  ),
1538
1538
  UniversalCreateParams,
1539
1539
  ),
@@ -1558,7 +1558,7 @@ class TestAsyncIsaacus:
1558
1558
  dict(
1559
1559
  model="kanon-universal-classifier",
1560
1560
  query="This is a confidentiality clause.",
1561
- text="I agree not to tell anyone about the document.",
1561
+ texts=["I agree not to tell anyone about the document."],
1562
1562
  ),
1563
1563
  UniversalCreateParams,
1564
1564
  ),
@@ -1599,7 +1599,7 @@ class TestAsyncIsaacus:
1599
1599
  response = await client.classifications.universal.with_raw_response.create(
1600
1600
  model="kanon-universal-classifier",
1601
1601
  query="This is a confidentiality clause.",
1602
- text="I agree not to tell anyone about the document.",
1602
+ texts=["I agree not to tell anyone about the document."],
1603
1603
  )
1604
1604
 
1605
1605
  assert response.retries_taken == failures_before_success
@@ -1628,7 +1628,7 @@ class TestAsyncIsaacus:
1628
1628
  response = await client.classifications.universal.with_raw_response.create(
1629
1629
  model="kanon-universal-classifier",
1630
1630
  query="This is a confidentiality clause.",
1631
- text="I agree not to tell anyone about the document.",
1631
+ texts=["I agree not to tell anyone about the document."],
1632
1632
  extra_headers={"x-stainless-retry-count": Omit()},
1633
1633
  )
1634
1634
 
@@ -1657,7 +1657,7 @@ class TestAsyncIsaacus:
1657
1657
  response = await client.classifications.universal.with_raw_response.create(
1658
1658
  model="kanon-universal-classifier",
1659
1659
  query="This is a confidentiality clause.",
1660
- text="I agree not to tell anyone about the document.",
1660
+ texts=["I agree not to tell anyone about the document."],
1661
1661
  extra_headers={"x-stainless-retry-count": "42"},
1662
1662
  )
1663
1663
 
@@ -492,12 +492,15 @@ def test_omitted_fields() -> None:
492
492
  resource_id: Optional[str] = None
493
493
 
494
494
  m = Model.construct()
495
+ assert m.resource_id is None
495
496
  assert "resource_id" not in m.model_fields_set
496
497
 
497
498
  m = Model.construct(resource_id=None)
499
+ assert m.resource_id is None
498
500
  assert "resource_id" in m.model_fields_set
499
501
 
500
502
  m = Model.construct(resource_id="foo")
503
+ assert m.resource_id == "foo"
501
504
  assert "resource_id" in m.model_fields_set
502
505
 
503
506
 
@@ -832,7 +835,7 @@ def test_discriminated_unions_invalid_data_uses_cache() -> None:
832
835
 
833
836
  @pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1")
834
837
  def test_type_alias_type() -> None:
835
- Alias = TypeAliasType("Alias", str)
838
+ Alias = TypeAliasType("Alias", str) # pyright: ignore
836
839
 
837
840
  class Model(BaseModel):
838
841
  alias: Alias
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.3.3"
3
- }
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