retab 0.0.42__py3-none-any.whl → 0.0.43__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.
Files changed (53) hide show
  1. retab/__init__.py +2 -1
  2. retab/client.py +16 -45
  3. retab/resources/consensus/client.py +1 -1
  4. retab/resources/consensus/responses.py +1 -1
  5. retab/resources/documents/client.py +94 -68
  6. retab/resources/documents/extractions.py +55 -46
  7. retab/resources/evaluations/client.py +32 -19
  8. retab/resources/evaluations/documents.py +12 -11
  9. retab/resources/evaluations/iterations.py +48 -30
  10. retab/resources/jsonlUtils.py +3 -4
  11. retab/resources/processors/automations/endpoints.py +49 -39
  12. retab/resources/processors/automations/links.py +52 -43
  13. retab/resources/processors/automations/mailboxes.py +74 -59
  14. retab/resources/processors/automations/outlook.py +104 -82
  15. retab/resources/processors/client.py +35 -30
  16. retab/resources/usage.py +2 -0
  17. retab/types/ai_models.py +1 -1
  18. retab/types/deprecated_evals.py +195 -0
  19. retab/types/evaluations/__init__.py +5 -2
  20. retab/types/evaluations/iterations.py +9 -43
  21. retab/types/evaluations/model.py +20 -22
  22. retab/types/extractions.py +1 -0
  23. retab/types/logs.py +5 -6
  24. retab/types/mime.py +1 -10
  25. retab/types/schemas/enhance.py +22 -5
  26. retab/types/schemas/evaluate.py +1 -1
  27. retab/types/schemas/object.py +26 -0
  28. retab/types/standards.py +2 -2
  29. retab/utils/__init__.py +3 -0
  30. retab/utils/ai_models.py +127 -12
  31. retab/utils/hashing.py +24 -0
  32. retab/utils/json_schema.py +1 -26
  33. retab/utils/mime.py +0 -17
  34. {retab-0.0.42.dist-info → retab-0.0.43.dist-info}/METADATA +3 -5
  35. {retab-0.0.42.dist-info → retab-0.0.43.dist-info}/RECORD +37 -51
  36. retab/_utils/__init__.py +0 -0
  37. retab/_utils/_model_cards/anthropic.yaml +0 -59
  38. retab/_utils/_model_cards/auto.yaml +0 -43
  39. retab/_utils/_model_cards/gemini.yaml +0 -117
  40. retab/_utils/_model_cards/openai.yaml +0 -301
  41. retab/_utils/_model_cards/xai.yaml +0 -28
  42. retab/_utils/ai_models.py +0 -138
  43. retab/_utils/benchmarking.py +0 -484
  44. retab/_utils/chat.py +0 -327
  45. retab/_utils/display.py +0 -440
  46. retab/_utils/json_schema.py +0 -2156
  47. retab/_utils/mime.py +0 -165
  48. retab/_utils/responses.py +0 -169
  49. retab/_utils/stream_context_managers.py +0 -52
  50. retab/_utils/usage/__init__.py +0 -0
  51. retab/_utils/usage/usage.py +0 -301
  52. {retab-0.0.42.dist-info → retab-0.0.43.dist-info}/WHEEL +0 -0
  53. {retab-0.0.42.dist-info → retab-0.0.43.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
  from typing import Any, List, Literal, Optional
4
4
 
5
5
  from pydantic import EmailStr, HttpUrl
6
- from pydantic_core import PydanticUndefined
6
+ from ....types.standards import FieldUnset
7
7
 
8
8
  from ...._resource import AsyncAPIResource, SyncAPIResource
9
9
  from ....utils.mime import prepare_mime_document
@@ -21,25 +21,32 @@ class MailBoxesMixin:
21
21
  name: str,
22
22
  processor_id: str,
23
23
  webhook_url: str,
24
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
25
- authorized_emails: list[EmailStr] = PydanticUndefined, # type: ignore[assignment]
26
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
27
- default_language: str = PydanticUndefined, # type: ignore[assignment]
28
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
24
+ authorized_domains: list[str] = FieldUnset,
25
+ authorized_emails: list[EmailStr] = FieldUnset,
26
+ webhook_headers: dict[str, str] = FieldUnset,
27
+ default_language: str = FieldUnset,
28
+ need_validation: bool = FieldUnset,
29
29
  ) -> PreparedRequest:
30
30
  """Create a new email automation configuration."""
31
- mailbox = Mailbox(
32
- name=name,
33
- processor_id=processor_id,
34
- default_language=default_language,
35
- webhook_url=webhook_url,
36
- webhook_headers=webhook_headers,
37
- need_validation=need_validation,
38
- email=email,
39
- authorized_domains=authorized_domains,
40
- authorized_emails=authorized_emails,
41
- )
42
- return PreparedRequest(method="POST", url=self.mailboxes_base_url, data=mailbox.model_dump(mode="json"))
31
+ mailbox_dict: dict[str, Any] = {
32
+ 'name': name,
33
+ 'processor_id': processor_id,
34
+ 'webhook_url': webhook_url,
35
+ 'email': email,
36
+ }
37
+ if default_language is not FieldUnset:
38
+ mailbox_dict['default_language'] = default_language
39
+ if webhook_headers is not FieldUnset:
40
+ mailbox_dict['webhook_headers'] = webhook_headers
41
+ if need_validation is not FieldUnset:
42
+ mailbox_dict['need_validation'] = need_validation
43
+ if authorized_domains is not FieldUnset:
44
+ mailbox_dict['authorized_domains'] = authorized_domains
45
+ if authorized_emails is not FieldUnset:
46
+ mailbox_dict['authorized_emails'] = authorized_emails
47
+
48
+ mailbox = Mailbox(**mailbox_dict)
49
+ return PreparedRequest(method="POST", url=self.mailboxes_base_url, data=mailbox.model_dump(mode="json", exclude_unset=True))
43
50
 
44
51
  def prepare_list(
45
52
  self,
@@ -73,24 +80,32 @@ class MailBoxesMixin:
73
80
  def prepare_update(
74
81
  self,
75
82
  mailbox_id: str,
76
- name: str = PydanticUndefined, # type: ignore[assignment]
77
- default_language: str = PydanticUndefined, # type: ignore[assignment]
78
- webhook_url: str = PydanticUndefined, # type: ignore[assignment]
79
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
80
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
81
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
82
- authorized_emails: list[str] = PydanticUndefined, # type: ignore[assignment]
83
+ name: str = FieldUnset,
84
+ default_language: str = FieldUnset,
85
+ webhook_url: str = FieldUnset,
86
+ webhook_headers: dict[str, str] = FieldUnset,
87
+ need_validation: bool = FieldUnset,
88
+ authorized_domains: list[str] = FieldUnset,
89
+ authorized_emails: list[str] = FieldUnset,
83
90
  ) -> PreparedRequest:
84
- update_mailbox_request = UpdateMailboxRequest(
85
- name=name,
86
- default_language=default_language,
87
- webhook_url=webhook_url,
88
- webhook_headers=webhook_headers,
89
- need_validation=need_validation,
90
- authorized_domains=authorized_domains,
91
- authorized_emails=authorized_emails,
92
- )
93
- return PreparedRequest(method="PUT", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", data=update_mailbox_request.model_dump(mode="json"))
91
+ update_dict: dict[str, Any] = {}
92
+ if name is not FieldUnset:
93
+ update_dict['name'] = name
94
+ if default_language is not FieldUnset:
95
+ update_dict['default_language'] = default_language
96
+ if webhook_url is not FieldUnset:
97
+ update_dict['webhook_url'] = webhook_url
98
+ if webhook_headers is not FieldUnset:
99
+ update_dict['webhook_headers'] = webhook_headers
100
+ if need_validation is not FieldUnset:
101
+ update_dict['need_validation'] = need_validation
102
+ if authorized_domains is not FieldUnset:
103
+ update_dict['authorized_domains'] = authorized_domains
104
+ if authorized_emails is not FieldUnset:
105
+ update_dict['authorized_emails'] = authorized_emails
106
+
107
+ update_mailbox_request = UpdateMailboxRequest(**update_dict)
108
+ return PreparedRequest(method="PUT", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", data=update_mailbox_request.model_dump(mode="json", exclude_unset=True))
94
109
 
95
110
  def prepare_delete(self, mailbox_id: str) -> PreparedRequest:
96
111
  return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", raise_for_status=True)
@@ -109,11 +124,11 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
109
124
  name: str,
110
125
  webhook_url: str,
111
126
  processor_id: str,
112
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
113
- authorized_emails: list[EmailStr] = PydanticUndefined, # type: ignore[assignment]
114
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
115
- default_language: str = PydanticUndefined, # type: ignore[assignment]
116
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
127
+ authorized_domains: list[str] = FieldUnset,
128
+ authorized_emails: list[EmailStr] = FieldUnset,
129
+ webhook_headers: dict[str, str] = FieldUnset,
130
+ default_language: str = FieldUnset,
131
+ need_validation: bool = FieldUnset,
117
132
  ) -> Mailbox:
118
133
  """Create a new email automation configuration.
119
134
 
@@ -202,13 +217,13 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
202
217
  def update(
203
218
  self,
204
219
  mailbox_id: str,
205
- name: str = PydanticUndefined, # type: ignore[assignment]
206
- default_language: str = PydanticUndefined, # type: ignore[assignment]
207
- webhook_url: str = PydanticUndefined, # type: ignore[assignment]
208
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
209
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
210
- authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
211
- authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
220
+ name: str = FieldUnset,
221
+ default_language: str = FieldUnset,
222
+ webhook_url: str = FieldUnset,
223
+ webhook_headers: dict[str, str] = FieldUnset,
224
+ need_validation: bool = FieldUnset,
225
+ authorized_domains: List[str] = FieldUnset,
226
+ authorized_emails: List[str] = FieldUnset,
212
227
  ) -> Mailbox:
213
228
  """Update an email automation configuration.
214
229
 
@@ -260,11 +275,11 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
260
275
  name: str,
261
276
  webhook_url: str,
262
277
  processor_id: str,
263
- authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
264
- authorized_emails: List[EmailStr] = PydanticUndefined, # type: ignore[assignment]
265
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
266
- default_language: str = PydanticUndefined, # type: ignore[assignment]
267
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
278
+ authorized_domains: List[str] = FieldUnset,
279
+ authorized_emails: List[EmailStr] = FieldUnset,
280
+ webhook_headers: dict[str, str] = FieldUnset,
281
+ default_language: str = FieldUnset,
282
+ need_validation: bool = FieldUnset,
268
283
  ) -> Mailbox:
269
284
  request = self.prepare_create(
270
285
  email=email,
@@ -315,13 +330,13 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
315
330
  async def update(
316
331
  self,
317
332
  mailbox_id: str,
318
- name: str = PydanticUndefined, # type: ignore[assignment]
319
- default_language: str = PydanticUndefined, # type: ignore[assignment]
320
- webhook_url: str = PydanticUndefined, # type: ignore[assignment]
321
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
322
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
323
- authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
324
- authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
333
+ name: str = FieldUnset,
334
+ default_language: str = FieldUnset,
335
+ webhook_url: str = FieldUnset,
336
+ webhook_headers: dict[str, str] = FieldUnset,
337
+ need_validation: bool = FieldUnset,
338
+ authorized_domains: List[str] = FieldUnset,
339
+ authorized_emails: List[str] = FieldUnset,
325
340
  ) -> Mailbox:
326
341
  request = self.prepare_update(
327
342
  mailbox_id=mailbox_id,
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Literal, List
2
2
 
3
- from pydantic_core import PydanticUndefined
3
+ from ....types.standards import FieldUnset
4
4
 
5
5
  from ...._resource import AsyncAPIResource, SyncAPIResource
6
6
  from ....types.automations.outlook import (
@@ -21,33 +21,44 @@ class OutlooksMixin:
21
21
  name: str,
22
22
  processor_id: str,
23
23
  webhook_url: str,
24
- default_language: str = PydanticUndefined, # type: ignore[assignment]
25
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
26
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
27
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
28
- authorized_emails: list[str] = PydanticUndefined, # type: ignore[assignment]
29
- layout_schema: dict[str, Any] = PydanticUndefined, # type: ignore[assignment]
30
- match_params: list[MatchParams] = PydanticUndefined, # type: ignore[assignment]
31
- fetch_params: list[FetchParams] = PydanticUndefined, # type: ignore[assignment]
24
+ default_language: str = FieldUnset,
25
+ webhook_headers: dict[str, str] = FieldUnset,
26
+ need_validation: bool = FieldUnset,
27
+ authorized_domains: list[str] = FieldUnset,
28
+ authorized_emails: list[str] = FieldUnset,
29
+ layout_schema: dict[str, Any] = FieldUnset,
30
+ match_params: list[MatchParams] = FieldUnset,
31
+ fetch_params: list[FetchParams] = FieldUnset,
32
32
  ) -> PreparedRequest:
33
+ # Build outlook dictionary with only provided fields
34
+ outlook_dict: dict[str, Any] = {
35
+ 'processor_id': processor_id,
36
+ 'name': name,
37
+ 'webhook_url': webhook_url,
38
+ }
39
+ if default_language is not FieldUnset:
40
+ outlook_dict['default_language'] = default_language
41
+ if webhook_headers is not FieldUnset:
42
+ outlook_dict['webhook_headers'] = webhook_headers
43
+ if need_validation is not FieldUnset:
44
+ outlook_dict['need_validation'] = need_validation
45
+ if authorized_domains is not FieldUnset:
46
+ outlook_dict['authorized_domains'] = authorized_domains
47
+ if authorized_emails is not FieldUnset:
48
+ outlook_dict['authorized_emails'] = authorized_emails
49
+ if layout_schema is not FieldUnset:
50
+ outlook_dict['layout_schema'] = layout_schema
51
+ if match_params is not FieldUnset:
52
+ outlook_dict['match_params'] = match_params
53
+ if fetch_params is not FieldUnset:
54
+ outlook_dict['fetch_params'] = fetch_params
55
+
33
56
  # Validate the data
34
- outlook_data = Outlook(
35
- processor_id=processor_id,
36
- name=name,
37
- default_language=default_language,
38
- webhook_url=webhook_url,
39
- webhook_headers=webhook_headers,
40
- need_validation=need_validation,
41
- authorized_domains=authorized_domains,
42
- authorized_emails=authorized_emails,
43
- layout_schema=layout_schema,
44
- match_params=match_params,
45
- fetch_params=fetch_params,
46
- )
57
+ outlook_data = Outlook(**outlook_dict)
47
58
  return PreparedRequest(
48
59
  method="POST",
49
60
  url=self.outlooks_base_url,
50
- data=outlook_data.model_dump(mode="json"),
61
+ data=outlook_data.model_dump(mode="json", exclude_unset=True),
51
62
  )
52
63
 
53
64
  def prepare_list(
@@ -80,34 +91,45 @@ class OutlooksMixin:
80
91
  def prepare_update(
81
92
  self,
82
93
  outlook_id: str,
83
- name: str = PydanticUndefined, # type: ignore[assignment]
84
- default_language: str = PydanticUndefined, # type: ignore[assignment]
85
- webhook_url: str = PydanticUndefined, # type: ignore[assignment]
86
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
87
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
88
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
89
- authorized_emails: list[str] = PydanticUndefined, # type: ignore[assignment]
90
- match_params: list[MatchParams] = PydanticUndefined, # type: ignore[assignment]
91
- fetch_params: list[FetchParams] = PydanticUndefined, # type: ignore[assignment]
92
- layout_schema: dict[str, Any] = PydanticUndefined, # type: ignore[assignment]
94
+ name: str = FieldUnset,
95
+ default_language: str = FieldUnset,
96
+ webhook_url: str = FieldUnset,
97
+ webhook_headers: dict[str, str] = FieldUnset,
98
+ need_validation: bool = FieldUnset,
99
+ authorized_domains: list[str] = FieldUnset,
100
+ authorized_emails: list[str] = FieldUnset,
101
+ match_params: list[MatchParams] = FieldUnset,
102
+ fetch_params: list[FetchParams] = FieldUnset,
103
+ layout_schema: dict[str, Any] = FieldUnset,
93
104
  ) -> PreparedRequest:
94
- update_outlook_request = UpdateOutlookRequest(
95
- name=name,
96
- default_language=default_language,
97
- webhook_url=webhook_url,
98
- webhook_headers=webhook_headers,
99
- need_validation=need_validation,
100
- authorized_domains=authorized_domains,
101
- authorized_emails=authorized_emails,
102
- layout_schema=layout_schema,
103
- match_params=match_params,
104
- fetch_params=fetch_params,
105
- )
105
+ update_dict: dict[str, Any] = {}
106
+ if name is not FieldUnset:
107
+ update_dict['name'] = name
108
+ if default_language is not FieldUnset:
109
+ update_dict['default_language'] = default_language
110
+ if webhook_url is not FieldUnset:
111
+ update_dict['webhook_url'] = webhook_url
112
+ if webhook_headers is not FieldUnset:
113
+ update_dict['webhook_headers'] = webhook_headers
114
+ if need_validation is not FieldUnset:
115
+ update_dict['need_validation'] = need_validation
116
+ if authorized_domains is not FieldUnset:
117
+ update_dict['authorized_domains'] = authorized_domains
118
+ if authorized_emails is not FieldUnset:
119
+ update_dict['authorized_emails'] = authorized_emails
120
+ if layout_schema is not FieldUnset:
121
+ update_dict['layout_schema'] = layout_schema
122
+ if match_params is not FieldUnset:
123
+ update_dict['match_params'] = match_params
124
+ if fetch_params is not FieldUnset:
125
+ update_dict['fetch_params'] = fetch_params
126
+
127
+ update_outlook_request = UpdateOutlookRequest(**update_dict)
106
128
 
107
129
  return PreparedRequest(
108
130
  method="PUT",
109
131
  url=f"{self.outlooks_base_url}/{outlook_id}",
110
- data=update_outlook_request.model_dump(mode="json"),
132
+ data=update_outlook_request.model_dump(mode="json", exclude_unset=True),
111
133
  )
112
134
 
113
135
  def prepare_delete(self, outlook_id: str) -> PreparedRequest:
@@ -125,14 +147,14 @@ class Outlooks(SyncAPIResource, OutlooksMixin):
125
147
  name: str,
126
148
  processor_id: str,
127
149
  webhook_url: str,
128
- default_language: str = PydanticUndefined, # type: ignore[assignment]
129
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
130
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
131
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
132
- authorized_emails: list[str] = PydanticUndefined, # type: ignore[assignment]
133
- layout_schema: dict[str, Any] = PydanticUndefined, # type: ignore[assignment]
134
- match_params: list[MatchParams] = PydanticUndefined, # type: ignore[assignment]
135
- fetch_params: list[FetchParams] = PydanticUndefined, # type: ignore[assignment]
150
+ default_language: str = FieldUnset,
151
+ webhook_headers: dict[str, str] = FieldUnset,
152
+ need_validation: bool = FieldUnset,
153
+ authorized_domains: list[str] = FieldUnset,
154
+ authorized_emails: list[str] = FieldUnset,
155
+ layout_schema: dict[str, Any] = FieldUnset,
156
+ match_params: list[MatchParams] = FieldUnset,
157
+ fetch_params: list[FetchParams] = FieldUnset,
136
158
  ) -> Outlook:
137
159
  """Create a new outlook automation configuration.
138
160
 
@@ -211,16 +233,16 @@ class Outlooks(SyncAPIResource, OutlooksMixin):
211
233
  def update(
212
234
  self,
213
235
  outlook_id: str,
214
- name: str = PydanticUndefined, # type: ignore[assignment]
215
- default_language: str = PydanticUndefined, # type: ignore[assignment]
216
- webhook_url: str = PydanticUndefined, # type: ignore[assignment]
217
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
218
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
219
- authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
220
- authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
221
- layout_schema: dict[str, Any] = PydanticUndefined, # type: ignore[assignment]
222
- match_params: List[MatchParams] = PydanticUndefined, # type: ignore[assignment]
223
- fetch_params: List[FetchParams] = PydanticUndefined, # type: ignore[assignment]
236
+ name: str = FieldUnset,
237
+ default_language: str = FieldUnset,
238
+ webhook_url: str = FieldUnset,
239
+ webhook_headers: dict[str, str] = FieldUnset,
240
+ need_validation: bool = FieldUnset,
241
+ authorized_domains: List[str] = FieldUnset,
242
+ authorized_emails: List[str] = FieldUnset,
243
+ layout_schema: dict[str, Any] = FieldUnset,
244
+ match_params: List[MatchParams] = FieldUnset,
245
+ fetch_params: List[FetchParams] = FieldUnset,
224
246
  ) -> Outlook:
225
247
  """Update an outlook automation configuration.
226
248
 
@@ -274,14 +296,14 @@ class AsyncOutlooks(AsyncAPIResource, OutlooksMixin):
274
296
  name: str,
275
297
  processor_id: str,
276
298
  webhook_url: str,
277
- default_language: str = PydanticUndefined, # type: ignore[assignment]
278
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
279
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
280
- authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
281
- authorized_emails: list[str] = PydanticUndefined, # type: ignore[assignment]
282
- layout_schema: dict[str, Any] = PydanticUndefined, # type: ignore[assignment]
283
- match_params: list[MatchParams] = PydanticUndefined, # type: ignore[assignment]
284
- fetch_params: list[FetchParams] = PydanticUndefined, # type: ignore[assignment]
299
+ default_language: str = FieldUnset,
300
+ webhook_headers: dict[str, str] = FieldUnset,
301
+ need_validation: bool = FieldUnset,
302
+ authorized_domains: list[str] = FieldUnset,
303
+ authorized_emails: list[str] = FieldUnset,
304
+ layout_schema: dict[str, Any] = FieldUnset,
305
+ match_params: list[MatchParams] = FieldUnset,
306
+ fetch_params: list[FetchParams] = FieldUnset,
285
307
  ) -> Outlook:
286
308
  request = self.prepare_create(
287
309
  name=name,
@@ -322,16 +344,16 @@ class AsyncOutlooks(AsyncAPIResource, OutlooksMixin):
322
344
  async def update(
323
345
  self,
324
346
  outlook_id: str,
325
- name: str = PydanticUndefined, # type: ignore[assignment]
326
- default_language: str = PydanticUndefined, # type: ignore[assignment]
327
- webhook_url: str = PydanticUndefined, # type: ignore[assignment]
328
- webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
329
- need_validation: bool = PydanticUndefined, # type: ignore[assignment]
330
- authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
331
- authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
332
- layout_schema: dict[str, Any] = PydanticUndefined, # type: ignore[assignment]
333
- match_params: List[MatchParams] = PydanticUndefined, # type: ignore[assignment]
334
- fetch_params: List[FetchParams] = PydanticUndefined, # type: ignore[assignment]
347
+ name: str = FieldUnset,
348
+ default_language: str = FieldUnset,
349
+ webhook_url: str = FieldUnset,
350
+ webhook_headers: dict[str, str] = FieldUnset,
351
+ need_validation: bool = FieldUnset,
352
+ authorized_domains: List[str] = FieldUnset,
353
+ authorized_emails: List[str] = FieldUnset,
354
+ layout_schema: dict[str, Any] = FieldUnset,
355
+ match_params: List[MatchParams] = FieldUnset,
356
+ fetch_params: List[FetchParams] = FieldUnset,
335
357
  ) -> Outlook:
336
358
  request = self.prepare_update(
337
359
  outlook_id=outlook_id,
@@ -6,8 +6,6 @@ from typing import Any, List, Literal
6
6
  import PIL.Image
7
7
  from openai.types.chat.chat_completion_reasoning_effort import ChatCompletionReasoningEffort
8
8
  from pydantic import BaseModel, HttpUrl
9
- from pydantic_core import PydanticUndefined
10
-
11
9
  from ..._resource import AsyncAPIResource, SyncAPIResource
12
10
  from ...utils.ai_models import assert_valid_model_extraction
13
11
  from ...utils.json_schema import load_json_schema
@@ -17,7 +15,7 @@ from ...types.documents.extractions import RetabParsedChatCompletion
17
15
  from ...types.logs import ProcessorConfig, UpdateProcessorRequest
18
16
  from ...types.modalities import Modality
19
17
  from ...types.pagination import ListMetadata
20
- from ...types.standards import PreparedRequest
18
+ from ...types.standards import PreparedRequest, FieldUnset
21
19
  from .automations.client import AsyncAutomations, Automations
22
20
 
23
21
 
@@ -35,30 +33,37 @@ class ProcessorsMixin:
35
33
  json_schema: dict[str, Any] | Path | str,
36
34
  modality: Modality = "native",
37
35
  model: str = "gpt-4o-mini",
38
- temperature: float = PydanticUndefined, # type: ignore[assignment]
39
- reasoning_effort: ChatCompletionReasoningEffort = PydanticUndefined, # type: ignore[assignment]
40
- image_resolution_dpi: int = PydanticUndefined, # type: ignore[assignment]
41
- browser_canvas: BrowserCanvas = PydanticUndefined, # type: ignore[assignment]
42
- n_consensus: int = PydanticUndefined, # type: ignore[assignment]
36
+ temperature: float = FieldUnset,
37
+ reasoning_effort: ChatCompletionReasoningEffort = FieldUnset,
38
+ image_resolution_dpi: int = FieldUnset,
39
+ browser_canvas: BrowserCanvas = FieldUnset,
40
+ n_consensus: int = FieldUnset,
43
41
  ) -> PreparedRequest:
44
42
  assert_valid_model_extraction(model)
45
43
 
46
44
  # Load the JSON schema from file path, string, or dict
47
45
  loaded_schema = load_json_schema(json_schema)
48
46
 
49
- processor_config = ProcessorConfig(
50
- name=name,
51
- json_schema=loaded_schema,
52
- modality=modality,
53
- model=model,
54
- temperature=temperature,
55
- reasoning_effort=reasoning_effort,
56
- image_resolution_dpi=image_resolution_dpi,
57
- browser_canvas=browser_canvas,
58
- n_consensus=n_consensus,
59
- )
47
+ config_dict = {
48
+ 'name': name,
49
+ 'json_schema': loaded_schema,
50
+ 'modality': modality,
51
+ 'model': model,
52
+ }
53
+ if temperature is not FieldUnset:
54
+ config_dict['temperature'] = temperature
55
+ if reasoning_effort is not FieldUnset:
56
+ config_dict['reasoning_effort'] = reasoning_effort
57
+ if image_resolution_dpi is not FieldUnset:
58
+ config_dict['image_resolution_dpi'] = image_resolution_dpi
59
+ if browser_canvas is not FieldUnset:
60
+ config_dict['browser_canvas'] = browser_canvas
61
+ if n_consensus is not FieldUnset:
62
+ config_dict['n_consensus'] = n_consensus
63
+
64
+ processor_config = ProcessorConfig(**config_dict)
60
65
 
61
- return PreparedRequest(method="POST", url="/v1/processors", data=processor_config.model_dump(mode="json"))
66
+ return PreparedRequest(method="POST", url="/v1/processors", data=processor_config.model_dump(mode="json", exclude_unset=True))
62
67
 
63
68
  def prepare_list(
64
69
  self,
@@ -215,11 +220,11 @@ class Processors(SyncAPIResource, ProcessorsMixin):
215
220
  json_schema: dict[str, Any] | Path | str,
216
221
  modality: Modality = "native",
217
222
  model: str = "gpt-4o-mini",
218
- temperature: float = PydanticUndefined, # type: ignore[assignment]
219
- reasoning_effort: ChatCompletionReasoningEffort = PydanticUndefined, # type: ignore[assignment]
220
- image_resolution_dpi: int = PydanticUndefined, # type: ignore[assignment]
221
- browser_canvas: BrowserCanvas = PydanticUndefined, # type: ignore[assignment]
222
- n_consensus: int = PydanticUndefined, # type: ignore[assignment]
223
+ temperature: float = FieldUnset,
224
+ reasoning_effort: ChatCompletionReasoningEffort = FieldUnset,
225
+ image_resolution_dpi: int = FieldUnset,
226
+ browser_canvas: BrowserCanvas = FieldUnset,
227
+ n_consensus: int = FieldUnset,
223
228
  ) -> ProcessorConfig:
224
229
  """Create a new processor configuration.
225
230
 
@@ -390,11 +395,11 @@ class AsyncProcessors(AsyncAPIResource, ProcessorsMixin):
390
395
  json_schema: dict[str, Any] | Path | str,
391
396
  modality: Modality = "native",
392
397
  model: str = "gpt-4o-mini",
393
- temperature: float = PydanticUndefined, # type: ignore[assignment]
394
- reasoning_effort: ChatCompletionReasoningEffort = PydanticUndefined, # type: ignore[assignment]
395
- image_resolution_dpi: int = PydanticUndefined, # type: ignore[assignment]
396
- browser_canvas: BrowserCanvas = PydanticUndefined, # type: ignore[assignment]
397
- n_consensus: int = PydanticUndefined, # type: ignore[assignment]
398
+ temperature: float = FieldUnset,
399
+ reasoning_effort: ChatCompletionReasoningEffort = FieldUnset,
400
+ image_resolution_dpi: int = FieldUnset,
401
+ browser_canvas: BrowserCanvas = FieldUnset,
402
+ n_consensus: int = FieldUnset,
398
403
  ) -> ProcessorConfig:
399
404
  request = self.prepare_create(
400
405
  name=name,
retab/resources/usage.py CHANGED
@@ -84,6 +84,7 @@ class Usage(SyncAPIResource, UsageMixin):
84
84
  def monthly_credits_usage(self) -> MonthlyUsageResponse:
85
85
  """
86
86
  Get monthly credits usage information.
87
+ Credits are calculated dynamically based on MIME type and consumption.
87
88
 
88
89
  Returns:
89
90
  dict: Monthly usage data including credits consumed and limits
@@ -198,6 +199,7 @@ class AsyncUsage(AsyncAPIResource, UsageMixin):
198
199
  async def monthly_credits_usage(self) -> MonthlyUsageResponse:
199
200
  """
200
201
  Get monthly credits usage information.
202
+ Credits are calculated dynamically based on MIME type and consumption.
201
203
 
202
204
  Returns:
203
205
  dict: Monthly usage data including credits consumed and limits
retab/types/ai_models.py CHANGED
@@ -79,7 +79,7 @@ class FinetunedModel(BaseModel):
79
79
 
80
80
  # Monthly Usage
81
81
  class MonthlyUsageResponseContent(BaseModel):
82
- request_count: int
82
+ credits_count: float # Changed to float to support decimal credits
83
83
 
84
84
 
85
85
  MonthlyUsageResponse = MonthlyUsageResponseContent