retab 0.0.81__py3-none-any.whl → 0.0.83__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.
- retab/client.py +3 -1
- retab/resources/documents/client.py +8 -8
- retab/resources/edit/__init__.py +3 -0
- retab/resources/edit/client.py +176 -0
- retab/resources/edit/templates/__init__.py +4 -0
- retab/resources/edit/templates/client.py +620 -0
- retab/types/documents/edit.py +13 -25
- retab/types/edit/__init__.py +16 -0
- retab/types/edit/templates.py +50 -0
- {retab-0.0.81.dist-info → retab-0.0.83.dist-info}/METADATA +1 -1
- {retab-0.0.81.dist-info → retab-0.0.83.dist-info}/RECORD +13 -7
- {retab-0.0.81.dist-info → retab-0.0.83.dist-info}/WHEEL +0 -0
- {retab-0.0.81.dist-info → retab-0.0.83.dist-info}/top_level.txt +0 -0
retab/client.py
CHANGED
|
@@ -10,7 +10,7 @@ import backoff.types
|
|
|
10
10
|
import httpx
|
|
11
11
|
import truststore
|
|
12
12
|
|
|
13
|
-
from .resources import documents, models, schemas, projects, extractions
|
|
13
|
+
from .resources import documents, models, schemas, projects, extractions, edit
|
|
14
14
|
from .types.standards import PreparedRequest, FieldUnset
|
|
15
15
|
|
|
16
16
|
|
|
@@ -188,6 +188,7 @@ class Retab(BaseRetab):
|
|
|
188
188
|
self.documents = documents.Documents(client=self)
|
|
189
189
|
self.models = models.Models(client=self)
|
|
190
190
|
self.schemas = schemas.Schemas(client=self)
|
|
191
|
+
self.edit = edit.Edit(client=self)
|
|
191
192
|
|
|
192
193
|
def _request(
|
|
193
194
|
self,
|
|
@@ -485,6 +486,7 @@ class AsyncRetab(BaseRetab):
|
|
|
485
486
|
self.documents = documents.AsyncDocuments(client=self)
|
|
486
487
|
self.models = models.AsyncModels(client=self)
|
|
487
488
|
self.schemas = schemas.AsyncSchemas(client=self)
|
|
489
|
+
self.edit = edit.AsyncEdit(client=self)
|
|
488
490
|
|
|
489
491
|
def _parse_response(self, response: httpx.Response) -> Any:
|
|
490
492
|
"""Parse response based on content-type.
|
|
@@ -119,14 +119,14 @@ class BaseDocumentsMixin:
|
|
|
119
119
|
|
|
120
120
|
def _prepare_edit(
|
|
121
121
|
self,
|
|
122
|
-
|
|
122
|
+
instructions: str,
|
|
123
123
|
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
|
124
124
|
model: str = FieldUnset,
|
|
125
125
|
template_id: str | None = FieldUnset,
|
|
126
126
|
**extra_body: Any,
|
|
127
127
|
) -> PreparedRequest:
|
|
128
128
|
request_dict: dict[str, Any] = {
|
|
129
|
-
"
|
|
129
|
+
"instructions": instructions,
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
if document is not None:
|
|
@@ -598,7 +598,7 @@ class Documents(SyncAPIResource, BaseDocumentsMixin):
|
|
|
598
598
|
|
|
599
599
|
def edit(
|
|
600
600
|
self,
|
|
601
|
-
|
|
601
|
+
instructions: str,
|
|
602
602
|
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
|
603
603
|
model: str = FieldUnset,
|
|
604
604
|
template_id: str | None = FieldUnset,
|
|
@@ -616,7 +616,7 @@ class Documents(SyncAPIResource, BaseDocumentsMixin):
|
|
|
616
616
|
Either `document` OR `template_id` must be provided, but not both.
|
|
617
617
|
|
|
618
618
|
Args:
|
|
619
|
-
|
|
619
|
+
instructions: Instructions describing how to fill the form fields.
|
|
620
620
|
document: The document to edit. Can be a file path (Path or str), file-like object, MIMEData, PIL Image, or URL.
|
|
621
621
|
Mutually exclusive with template_id.
|
|
622
622
|
model: The LLM model to use for inference. Defaults to "retab-small".
|
|
@@ -632,7 +632,7 @@ class Documents(SyncAPIResource, BaseDocumentsMixin):
|
|
|
632
632
|
HTTPException: If the request fails.
|
|
633
633
|
"""
|
|
634
634
|
request = self._prepare_edit(
|
|
635
|
-
|
|
635
|
+
instructions=instructions,
|
|
636
636
|
document=document,
|
|
637
637
|
model=model,
|
|
638
638
|
template_id=template_id,
|
|
@@ -993,7 +993,7 @@ class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
|
|
993
993
|
|
|
994
994
|
async def edit(
|
|
995
995
|
self,
|
|
996
|
-
|
|
996
|
+
instructions: str,
|
|
997
997
|
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
|
998
998
|
model: str = FieldUnset,
|
|
999
999
|
template_id: str | None = FieldUnset,
|
|
@@ -1011,7 +1011,7 @@ class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
|
|
1011
1011
|
Either `document` OR `template_id` must be provided, but not both.
|
|
1012
1012
|
|
|
1013
1013
|
Args:
|
|
1014
|
-
|
|
1014
|
+
instructions: Instructions describing how to fill the form fields.
|
|
1015
1015
|
document: The document to edit. Can be a file path (Path or str), file-like object, MIMEData, PIL Image, or URL.
|
|
1016
1016
|
Mutually exclusive with template_id.
|
|
1017
1017
|
model: The LLM model to use for inference. Defaults to "gemini-2.5-pro".
|
|
@@ -1027,7 +1027,7 @@ class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
|
|
1027
1027
|
HTTPException: If the request fails.
|
|
1028
1028
|
"""
|
|
1029
1029
|
request = self._prepare_edit(
|
|
1030
|
-
|
|
1030
|
+
instructions=instructions,
|
|
1031
1031
|
document=document,
|
|
1032
1032
|
model=model,
|
|
1033
1033
|
template_id=template_id,
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Edit SDK client - Wrapper for document editing functionality.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from io import IOBase
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import PIL.Image
|
|
10
|
+
from pydantic import HttpUrl
|
|
11
|
+
|
|
12
|
+
from ..._resource import AsyncAPIResource, SyncAPIResource
|
|
13
|
+
from ...utils.mime import prepare_mime_document
|
|
14
|
+
from ...types.documents.edit import (
|
|
15
|
+
EditRequest,
|
|
16
|
+
EditResponse,
|
|
17
|
+
)
|
|
18
|
+
from ...types.mime import MIMEData
|
|
19
|
+
from ...types.standards import PreparedRequest, FieldUnset
|
|
20
|
+
from .templates import Templates, AsyncTemplates
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BaseEditMixin:
|
|
24
|
+
"""Shared methods for preparing edit API requests."""
|
|
25
|
+
|
|
26
|
+
def _prepare_fill_document(
|
|
27
|
+
self,
|
|
28
|
+
instructions: str,
|
|
29
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
|
30
|
+
model: str = FieldUnset,
|
|
31
|
+
template_id: str | None = FieldUnset,
|
|
32
|
+
**extra_body: Any,
|
|
33
|
+
) -> PreparedRequest:
|
|
34
|
+
request_dict: dict[str, Any] = {
|
|
35
|
+
"instructions": instructions,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if document is not None:
|
|
39
|
+
mime_document = prepare_mime_document(document)
|
|
40
|
+
request_dict["document"] = mime_document
|
|
41
|
+
|
|
42
|
+
if model is not FieldUnset:
|
|
43
|
+
request_dict["model"] = model
|
|
44
|
+
if template_id is not FieldUnset:
|
|
45
|
+
request_dict["template_id"] = template_id
|
|
46
|
+
|
|
47
|
+
# Merge any extra fields provided by the caller
|
|
48
|
+
if extra_body:
|
|
49
|
+
request_dict.update(extra_body)
|
|
50
|
+
|
|
51
|
+
edit_request = EditRequest(**request_dict)
|
|
52
|
+
return PreparedRequest(
|
|
53
|
+
method="POST",
|
|
54
|
+
url="/v1/edit/fill-document",
|
|
55
|
+
data=edit_request.model_dump(mode="json", exclude_unset=True),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Edit(SyncAPIResource, BaseEditMixin):
|
|
60
|
+
"""Edit API wrapper for synchronous usage."""
|
|
61
|
+
|
|
62
|
+
def __init__(self, client: Any) -> None:
|
|
63
|
+
super().__init__(client=client)
|
|
64
|
+
self.templates = Templates(client=client)
|
|
65
|
+
|
|
66
|
+
def fill_document(
|
|
67
|
+
self,
|
|
68
|
+
instructions: str,
|
|
69
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
|
70
|
+
model: str = FieldUnset,
|
|
71
|
+
template_id: str | None = FieldUnset,
|
|
72
|
+
**extra_body: Any,
|
|
73
|
+
) -> EditResponse:
|
|
74
|
+
"""
|
|
75
|
+
Edit a document by inferring form fields and filling them with provided instructions.
|
|
76
|
+
|
|
77
|
+
This method performs:
|
|
78
|
+
1. Detection to identify form field bounding boxes
|
|
79
|
+
2. LLM inference to name and describe detected fields
|
|
80
|
+
3. LLM-based form filling using the provided instructions
|
|
81
|
+
4. Returns the filled document with form field values populated
|
|
82
|
+
|
|
83
|
+
Either `document` OR `template_id` must be provided, but not both.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
instructions: Instructions describing how to fill the form fields.
|
|
87
|
+
document: The document to edit. Can be a file path (Path or str), file-like object,
|
|
88
|
+
MIMEData, PIL Image, or URL. Mutually exclusive with template_id.
|
|
89
|
+
model: The LLM model to use for inference. Defaults to "retab-small".
|
|
90
|
+
template_id: Template ID to use for filling. When provided, uses the template's
|
|
91
|
+
pre-defined form fields and empty PDF. Only works for PDF documents.
|
|
92
|
+
Mutually exclusive with document.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
EditResponse: Response containing:
|
|
96
|
+
- form_data: List of form fields with filled values
|
|
97
|
+
- filled_document: Document with filled form values (MIMEData)
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
HTTPException: If the request fails.
|
|
101
|
+
|
|
102
|
+
Supported document formats:
|
|
103
|
+
- PDF: Native form field detection and filling
|
|
104
|
+
- DOCX/DOC: Native editing to preserve styles and formatting
|
|
105
|
+
- PPTX/PPT: Native editing for presentations
|
|
106
|
+
- XLSX/XLS: Native editing for spreadsheets
|
|
107
|
+
"""
|
|
108
|
+
request = self._prepare_fill_document(
|
|
109
|
+
instructions=instructions,
|
|
110
|
+
document=document,
|
|
111
|
+
model=model,
|
|
112
|
+
template_id=template_id,
|
|
113
|
+
**extra_body,
|
|
114
|
+
)
|
|
115
|
+
response = self._client._prepared_request(request)
|
|
116
|
+
return EditResponse.model_validate(response)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class AsyncEdit(AsyncAPIResource, BaseEditMixin):
|
|
120
|
+
"""Edit API wrapper for asynchronous usage."""
|
|
121
|
+
|
|
122
|
+
def __init__(self, client: Any) -> None:
|
|
123
|
+
super().__init__(client=client)
|
|
124
|
+
self.templates = AsyncTemplates(client=client)
|
|
125
|
+
|
|
126
|
+
async def fill_document(
|
|
127
|
+
self,
|
|
128
|
+
instructions: str,
|
|
129
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
|
130
|
+
model: str = FieldUnset,
|
|
131
|
+
template_id: str | None = FieldUnset,
|
|
132
|
+
**extra_body: Any,
|
|
133
|
+
) -> EditResponse:
|
|
134
|
+
"""
|
|
135
|
+
Edit a document by inferring form fields and filling them with provided instructions asynchronously.
|
|
136
|
+
|
|
137
|
+
This method performs:
|
|
138
|
+
1. Detection to identify form field bounding boxes
|
|
139
|
+
2. LLM inference to name and describe detected fields
|
|
140
|
+
3. LLM-based form filling using the provided instructions
|
|
141
|
+
4. Returns the filled document with form field values populated
|
|
142
|
+
|
|
143
|
+
Either `document` OR `template_id` must be provided, but not both.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
instructions: Instructions describing how to fill the form fields.
|
|
147
|
+
document: The document to edit. Can be a file path (Path or str), file-like object,
|
|
148
|
+
MIMEData, PIL Image, or URL. Mutually exclusive with template_id.
|
|
149
|
+
model: The LLM model to use for inference. Defaults to "retab-small".
|
|
150
|
+
template_id: Template ID to use for filling. When provided, uses the template's
|
|
151
|
+
pre-defined form fields and empty PDF. Only works for PDF documents.
|
|
152
|
+
Mutually exclusive with document.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
EditResponse: Response containing:
|
|
156
|
+
- form_data: List of form fields with filled values
|
|
157
|
+
- filled_document: Document with filled form values (MIMEData)
|
|
158
|
+
|
|
159
|
+
Raises:
|
|
160
|
+
HTTPException: If the request fails.
|
|
161
|
+
|
|
162
|
+
Supported document formats:
|
|
163
|
+
- PDF: Native form field detection and filling
|
|
164
|
+
- DOCX/DOC: Native editing to preserve styles and formatting
|
|
165
|
+
- PPTX/PPT: Native editing for presentations
|
|
166
|
+
- XLSX/XLS: Native editing for spreadsheets
|
|
167
|
+
"""
|
|
168
|
+
request = self._prepare_fill_document(
|
|
169
|
+
instructions=instructions,
|
|
170
|
+
document=document,
|
|
171
|
+
model=model,
|
|
172
|
+
template_id=template_id,
|
|
173
|
+
**extra_body,
|
|
174
|
+
)
|
|
175
|
+
response = await self._client._prepared_request(request)
|
|
176
|
+
return EditResponse.model_validate(response)
|
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Edit Templates SDK client - Wrapper for edit template management.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from io import IOBase
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Literal, List
|
|
8
|
+
|
|
9
|
+
import PIL.Image
|
|
10
|
+
from pydantic import HttpUrl
|
|
11
|
+
|
|
12
|
+
from ...._resource import AsyncAPIResource, SyncAPIResource
|
|
13
|
+
from ....utils.mime import prepare_mime_document
|
|
14
|
+
from ....types.documents.edit import (
|
|
15
|
+
FormField,
|
|
16
|
+
InferFormSchemaRequest,
|
|
17
|
+
InferFormSchemaResponse,
|
|
18
|
+
EditResponse,
|
|
19
|
+
)
|
|
20
|
+
from ....types.edit.templates import EditTemplate, FillTemplateRequest
|
|
21
|
+
from ....types.mime import MIMEData
|
|
22
|
+
from ....types.standards import PreparedRequest, FieldUnset
|
|
23
|
+
from ....types.pagination import PaginatedList
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BaseTemplatesMixin:
|
|
27
|
+
"""Shared methods for preparing template API requests."""
|
|
28
|
+
|
|
29
|
+
def _prepare_list(
|
|
30
|
+
self,
|
|
31
|
+
before: str | None = None,
|
|
32
|
+
after: str | None = None,
|
|
33
|
+
limit: int = 10,
|
|
34
|
+
order: Literal["asc", "desc"] = "desc",
|
|
35
|
+
filename: str | None = None,
|
|
36
|
+
mime_type: str | None = None,
|
|
37
|
+
**extra_params: Any,
|
|
38
|
+
) -> PreparedRequest:
|
|
39
|
+
params: dict[str, Any] = {
|
|
40
|
+
"limit": limit,
|
|
41
|
+
"order": order,
|
|
42
|
+
}
|
|
43
|
+
if before:
|
|
44
|
+
params["before"] = before
|
|
45
|
+
if after:
|
|
46
|
+
params["after"] = after
|
|
47
|
+
if filename:
|
|
48
|
+
params["filename"] = filename
|
|
49
|
+
if mime_type:
|
|
50
|
+
params["mime_type"] = mime_type
|
|
51
|
+
if extra_params:
|
|
52
|
+
params.update(extra_params)
|
|
53
|
+
|
|
54
|
+
return PreparedRequest(
|
|
55
|
+
method="GET",
|
|
56
|
+
url="/v1/edit/templates",
|
|
57
|
+
params=params,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def _prepare_get(self, template_id: str) -> PreparedRequest:
|
|
61
|
+
return PreparedRequest(
|
|
62
|
+
method="GET",
|
|
63
|
+
url=f"/v1/edit/templates/{template_id}",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def _prepare_create(
|
|
67
|
+
self,
|
|
68
|
+
name: str,
|
|
69
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
|
70
|
+
form_fields: list[FormField],
|
|
71
|
+
**extra_body: Any,
|
|
72
|
+
) -> PreparedRequest:
|
|
73
|
+
mime_document = prepare_mime_document(document)
|
|
74
|
+
|
|
75
|
+
request_dict: dict[str, Any] = {
|
|
76
|
+
"name": name,
|
|
77
|
+
"document": mime_document,
|
|
78
|
+
"form_fields": [f.model_dump() if hasattr(f, 'model_dump') else f for f in form_fields],
|
|
79
|
+
}
|
|
80
|
+
if extra_body:
|
|
81
|
+
request_dict.update(extra_body)
|
|
82
|
+
|
|
83
|
+
return PreparedRequest(
|
|
84
|
+
method="POST",
|
|
85
|
+
url="/v1/edit/templates",
|
|
86
|
+
data=request_dict,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
def _prepare_update(
|
|
90
|
+
self,
|
|
91
|
+
template_id: str,
|
|
92
|
+
name: str | None = None,
|
|
93
|
+
form_fields: list[FormField] | None = None,
|
|
94
|
+
**extra_body: Any,
|
|
95
|
+
) -> PreparedRequest:
|
|
96
|
+
request_dict: dict[str, Any] = {}
|
|
97
|
+
if name is not None:
|
|
98
|
+
request_dict["name"] = name
|
|
99
|
+
if form_fields is not None:
|
|
100
|
+
request_dict["form_fields"] = [f.model_dump() if hasattr(f, 'model_dump') else f for f in form_fields]
|
|
101
|
+
if extra_body:
|
|
102
|
+
request_dict.update(extra_body)
|
|
103
|
+
|
|
104
|
+
return PreparedRequest(
|
|
105
|
+
method="PATCH",
|
|
106
|
+
url=f"/v1/edit/templates/{template_id}",
|
|
107
|
+
data=request_dict,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def _prepare_delete(self, template_id: str) -> PreparedRequest:
|
|
111
|
+
return PreparedRequest(
|
|
112
|
+
method="DELETE",
|
|
113
|
+
url=f"/v1/edit/templates/{template_id}",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def _prepare_duplicate(
|
|
117
|
+
self,
|
|
118
|
+
template_id: str,
|
|
119
|
+
name: str | None = None,
|
|
120
|
+
**extra_body: Any,
|
|
121
|
+
) -> PreparedRequest:
|
|
122
|
+
request_dict: dict[str, Any] = {}
|
|
123
|
+
if name is not None:
|
|
124
|
+
request_dict["name"] = name
|
|
125
|
+
if extra_body:
|
|
126
|
+
request_dict.update(extra_body)
|
|
127
|
+
|
|
128
|
+
return PreparedRequest(
|
|
129
|
+
method="POST",
|
|
130
|
+
url=f"/v1/edit/templates/{template_id}/duplicate",
|
|
131
|
+
data=request_dict,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def _prepare_generate(
|
|
135
|
+
self,
|
|
136
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
|
137
|
+
model: str = FieldUnset,
|
|
138
|
+
instructions: str | None = FieldUnset,
|
|
139
|
+
**extra_body: Any,
|
|
140
|
+
) -> PreparedRequest:
|
|
141
|
+
mime_document = prepare_mime_document(document)
|
|
142
|
+
|
|
143
|
+
request_dict: dict[str, Any] = {
|
|
144
|
+
"document": mime_document,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if model is not FieldUnset:
|
|
148
|
+
request_dict["model"] = model
|
|
149
|
+
if instructions is not FieldUnset:
|
|
150
|
+
request_dict["instructions"] = instructions
|
|
151
|
+
if extra_body:
|
|
152
|
+
request_dict.update(extra_body)
|
|
153
|
+
|
|
154
|
+
infer_request = InferFormSchemaRequest(**request_dict)
|
|
155
|
+
return PreparedRequest(
|
|
156
|
+
method="POST",
|
|
157
|
+
url="/v1/edit/templates/generate",
|
|
158
|
+
data=infer_request.model_dump(mode="json", exclude_unset=True),
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def _prepare_fill(
|
|
162
|
+
self,
|
|
163
|
+
template_id: str,
|
|
164
|
+
instructions: str,
|
|
165
|
+
model: str = FieldUnset,
|
|
166
|
+
**extra_body: Any,
|
|
167
|
+
) -> PreparedRequest:
|
|
168
|
+
request_dict: dict[str, Any] = {
|
|
169
|
+
"template_id": template_id,
|
|
170
|
+
"instructions": instructions,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if model is not FieldUnset:
|
|
174
|
+
request_dict["model"] = model
|
|
175
|
+
if extra_body:
|
|
176
|
+
request_dict.update(extra_body)
|
|
177
|
+
|
|
178
|
+
fill_request = FillTemplateRequest(**request_dict)
|
|
179
|
+
return PreparedRequest(
|
|
180
|
+
method="POST",
|
|
181
|
+
url="/v1/edit/templates/fill",
|
|
182
|
+
data=fill_request.model_dump(mode="json", exclude_unset=True),
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class Templates(SyncAPIResource, BaseTemplatesMixin):
|
|
187
|
+
"""Templates API wrapper for synchronous usage."""
|
|
188
|
+
|
|
189
|
+
def __init__(self, client: Any) -> None:
|
|
190
|
+
super().__init__(client=client)
|
|
191
|
+
|
|
192
|
+
def list(
|
|
193
|
+
self,
|
|
194
|
+
before: str | None = None,
|
|
195
|
+
after: str | None = None,
|
|
196
|
+
limit: int = 10,
|
|
197
|
+
order: Literal["asc", "desc"] = "desc",
|
|
198
|
+
filename: str | None = None,
|
|
199
|
+
mime_type: str | None = None,
|
|
200
|
+
**extra_params: Any,
|
|
201
|
+
) -> PaginatedList:
|
|
202
|
+
"""
|
|
203
|
+
List edit templates with pagination and optional filtering.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
before: Cursor for backward pagination
|
|
207
|
+
after: Cursor for forward pagination
|
|
208
|
+
limit: Number of items per page (1-100, default 10)
|
|
209
|
+
order: Sort order ("asc" or "desc", default "desc")
|
|
210
|
+
filename: Filter by filename (partial match)
|
|
211
|
+
mime_type: Filter by MIME type
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
PaginatedList: Paginated list of templates (data contains EditTemplate objects)
|
|
215
|
+
"""
|
|
216
|
+
request = self._prepare_list(
|
|
217
|
+
before=before,
|
|
218
|
+
after=after,
|
|
219
|
+
limit=limit,
|
|
220
|
+
order=order,
|
|
221
|
+
filename=filename,
|
|
222
|
+
mime_type=mime_type,
|
|
223
|
+
**extra_params,
|
|
224
|
+
)
|
|
225
|
+
response = self._client._prepared_request(request)
|
|
226
|
+
return PaginatedList.model_validate(response)
|
|
227
|
+
|
|
228
|
+
def get(self, template_id: str) -> EditTemplate:
|
|
229
|
+
"""
|
|
230
|
+
Get a specific edit template by ID.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
template_id: The template ID to retrieve
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
EditTemplate: The template details
|
|
237
|
+
"""
|
|
238
|
+
request = self._prepare_get(template_id)
|
|
239
|
+
response = self._client._prepared_request(request)
|
|
240
|
+
return EditTemplate.model_validate(response)
|
|
241
|
+
|
|
242
|
+
def create(
|
|
243
|
+
self,
|
|
244
|
+
name: str,
|
|
245
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
|
246
|
+
form_fields: List[FormField],
|
|
247
|
+
**extra_body: Any,
|
|
248
|
+
) -> EditTemplate:
|
|
249
|
+
"""
|
|
250
|
+
Create a new edit template.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
name: Name of the template
|
|
254
|
+
document: The PDF document to use as the template
|
|
255
|
+
form_fields: List of form fields in the template
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
EditTemplate: The created template
|
|
259
|
+
"""
|
|
260
|
+
request = self._prepare_create(
|
|
261
|
+
name=name,
|
|
262
|
+
document=document,
|
|
263
|
+
form_fields=form_fields,
|
|
264
|
+
**extra_body,
|
|
265
|
+
)
|
|
266
|
+
response = self._client._prepared_request(request)
|
|
267
|
+
return EditTemplate.model_validate(response)
|
|
268
|
+
|
|
269
|
+
def update(
|
|
270
|
+
self,
|
|
271
|
+
template_id: str,
|
|
272
|
+
name: str | None = None,
|
|
273
|
+
form_fields: List[FormField] | None = None,
|
|
274
|
+
**extra_body: Any,
|
|
275
|
+
) -> EditTemplate:
|
|
276
|
+
"""
|
|
277
|
+
Update an existing edit template.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
template_id: The template ID to update
|
|
281
|
+
name: New name for the template (optional)
|
|
282
|
+
form_fields: New form fields (optional)
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
EditTemplate: The updated template
|
|
286
|
+
"""
|
|
287
|
+
request = self._prepare_update(
|
|
288
|
+
template_id=template_id,
|
|
289
|
+
name=name,
|
|
290
|
+
form_fields=form_fields,
|
|
291
|
+
**extra_body,
|
|
292
|
+
)
|
|
293
|
+
response = self._client._prepared_request(request)
|
|
294
|
+
return EditTemplate.model_validate(response)
|
|
295
|
+
|
|
296
|
+
def delete(self, template_id: str) -> None:
|
|
297
|
+
"""
|
|
298
|
+
Delete an edit template.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
template_id: The template ID to delete
|
|
302
|
+
"""
|
|
303
|
+
request = self._prepare_delete(template_id)
|
|
304
|
+
self._client._prepared_request(request)
|
|
305
|
+
|
|
306
|
+
def duplicate(
|
|
307
|
+
self,
|
|
308
|
+
template_id: str,
|
|
309
|
+
name: str | None = None,
|
|
310
|
+
**extra_body: Any,
|
|
311
|
+
) -> EditTemplate:
|
|
312
|
+
"""
|
|
313
|
+
Duplicate an existing edit template.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
template_id: The template ID to duplicate
|
|
317
|
+
name: Name for the duplicated template (defaults to "<original> (copy)")
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
EditTemplate: The duplicated template
|
|
321
|
+
"""
|
|
322
|
+
request = self._prepare_duplicate(
|
|
323
|
+
template_id=template_id,
|
|
324
|
+
name=name,
|
|
325
|
+
**extra_body,
|
|
326
|
+
)
|
|
327
|
+
response = self._client._prepared_request(request)
|
|
328
|
+
return EditTemplate.model_validate(response)
|
|
329
|
+
|
|
330
|
+
def generate(
|
|
331
|
+
self,
|
|
332
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
|
333
|
+
model: str = FieldUnset,
|
|
334
|
+
instructions: str | None = FieldUnset,
|
|
335
|
+
**extra_body: Any,
|
|
336
|
+
) -> InferFormSchemaResponse:
|
|
337
|
+
"""
|
|
338
|
+
Infer form schema from a PDF document.
|
|
339
|
+
|
|
340
|
+
This method combines computer vision for precise bounding box detection
|
|
341
|
+
with LLM for semantic field naming (key, description) and type classification.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
document: The PDF document to analyze
|
|
345
|
+
model: The LLM model to use for field naming (default: "retab-small")
|
|
346
|
+
instructions: Optional instructions to guide form field detection
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
InferFormSchemaResponse: Response containing:
|
|
350
|
+
- form_schema: The detected form schema
|
|
351
|
+
- annotated_pdf: PDF with bounding boxes for visual verification
|
|
352
|
+
- detection_count: Number of fields detected
|
|
353
|
+
|
|
354
|
+
Note:
|
|
355
|
+
Only PDF documents are supported for form schema inference.
|
|
356
|
+
"""
|
|
357
|
+
request = self._prepare_generate(
|
|
358
|
+
document=document,
|
|
359
|
+
model=model,
|
|
360
|
+
instructions=instructions,
|
|
361
|
+
**extra_body,
|
|
362
|
+
)
|
|
363
|
+
response = self._client._prepared_request(request)
|
|
364
|
+
return InferFormSchemaResponse.model_validate(response)
|
|
365
|
+
|
|
366
|
+
def fill(
|
|
367
|
+
self,
|
|
368
|
+
template_id: str,
|
|
369
|
+
instructions: str,
|
|
370
|
+
model: str = FieldUnset,
|
|
371
|
+
**extra_body: Any,
|
|
372
|
+
) -> EditResponse:
|
|
373
|
+
"""
|
|
374
|
+
Fill a PDF form using a pre-defined template.
|
|
375
|
+
|
|
376
|
+
This method uses a template's pre-defined form fields to fill a PDF form,
|
|
377
|
+
skipping the field detection step for faster processing.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
template_id: The template ID to use for filling
|
|
381
|
+
instructions: Instructions describing how to fill the form fields
|
|
382
|
+
model: The LLM model to use for inference (default: "retab-small")
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
EditResponse: Response containing:
|
|
386
|
+
- form_data: List of form fields with filled values
|
|
387
|
+
- filled_document: The filled PDF document as MIMEData
|
|
388
|
+
|
|
389
|
+
Use cases:
|
|
390
|
+
- Batch processing of the same form with different data
|
|
391
|
+
- Faster form filling when field detection is already done
|
|
392
|
+
- Consistent field mapping across multiple fills
|
|
393
|
+
"""
|
|
394
|
+
request = self._prepare_fill(
|
|
395
|
+
template_id=template_id,
|
|
396
|
+
instructions=instructions,
|
|
397
|
+
model=model,
|
|
398
|
+
**extra_body,
|
|
399
|
+
)
|
|
400
|
+
response = self._client._prepared_request(request)
|
|
401
|
+
return EditResponse.model_validate(response)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
class AsyncTemplates(AsyncAPIResource, BaseTemplatesMixin):
|
|
405
|
+
"""Templates API wrapper for asynchronous usage."""
|
|
406
|
+
|
|
407
|
+
def __init__(self, client: Any) -> None:
|
|
408
|
+
super().__init__(client=client)
|
|
409
|
+
|
|
410
|
+
async def list(
|
|
411
|
+
self,
|
|
412
|
+
before: str | None = None,
|
|
413
|
+
after: str | None = None,
|
|
414
|
+
limit: int = 10,
|
|
415
|
+
order: Literal["asc", "desc"] = "desc",
|
|
416
|
+
filename: str | None = None,
|
|
417
|
+
mime_type: str | None = None,
|
|
418
|
+
**extra_params: Any,
|
|
419
|
+
) -> PaginatedList:
|
|
420
|
+
"""
|
|
421
|
+
List edit templates with pagination and optional filtering.
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
before: Cursor for backward pagination
|
|
425
|
+
after: Cursor for forward pagination
|
|
426
|
+
limit: Number of items per page (1-100, default 10)
|
|
427
|
+
order: Sort order ("asc" or "desc", default "desc")
|
|
428
|
+
filename: Filter by filename (partial match)
|
|
429
|
+
mime_type: Filter by MIME type
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
PaginatedList: Paginated list of templates (data contains EditTemplate objects)
|
|
433
|
+
"""
|
|
434
|
+
request = self._prepare_list(
|
|
435
|
+
before=before,
|
|
436
|
+
after=after,
|
|
437
|
+
limit=limit,
|
|
438
|
+
order=order,
|
|
439
|
+
filename=filename,
|
|
440
|
+
mime_type=mime_type,
|
|
441
|
+
**extra_params,
|
|
442
|
+
)
|
|
443
|
+
response = await self._client._prepared_request(request)
|
|
444
|
+
return PaginatedList.model_validate(response)
|
|
445
|
+
|
|
446
|
+
async def get(self, template_id: str) -> EditTemplate:
|
|
447
|
+
"""
|
|
448
|
+
Get a specific edit template by ID.
|
|
449
|
+
|
|
450
|
+
Args:
|
|
451
|
+
template_id: The template ID to retrieve
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
EditTemplate: The template details
|
|
455
|
+
"""
|
|
456
|
+
request = self._prepare_get(template_id)
|
|
457
|
+
response = await self._client._prepared_request(request)
|
|
458
|
+
return EditTemplate.model_validate(response)
|
|
459
|
+
|
|
460
|
+
async def create(
|
|
461
|
+
self,
|
|
462
|
+
name: str,
|
|
463
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
|
464
|
+
form_fields: List[FormField],
|
|
465
|
+
**extra_body: Any,
|
|
466
|
+
) -> EditTemplate:
|
|
467
|
+
"""
|
|
468
|
+
Create a new edit template.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
name: Name of the template
|
|
472
|
+
document: The PDF document to use as the template
|
|
473
|
+
form_fields: List of form fields in the template
|
|
474
|
+
|
|
475
|
+
Returns:
|
|
476
|
+
EditTemplate: The created template
|
|
477
|
+
"""
|
|
478
|
+
request = self._prepare_create(
|
|
479
|
+
name=name,
|
|
480
|
+
document=document,
|
|
481
|
+
form_fields=form_fields,
|
|
482
|
+
**extra_body,
|
|
483
|
+
)
|
|
484
|
+
response = await self._client._prepared_request(request)
|
|
485
|
+
return EditTemplate.model_validate(response)
|
|
486
|
+
|
|
487
|
+
async def update(
|
|
488
|
+
self,
|
|
489
|
+
template_id: str,
|
|
490
|
+
name: str | None = None,
|
|
491
|
+
form_fields: List[FormField] | None = None,
|
|
492
|
+
**extra_body: Any,
|
|
493
|
+
) -> EditTemplate:
|
|
494
|
+
"""
|
|
495
|
+
Update an existing edit template.
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
template_id: The template ID to update
|
|
499
|
+
name: New name for the template (optional)
|
|
500
|
+
form_fields: New form fields (optional)
|
|
501
|
+
|
|
502
|
+
Returns:
|
|
503
|
+
EditTemplate: The updated template
|
|
504
|
+
"""
|
|
505
|
+
request = self._prepare_update(
|
|
506
|
+
template_id=template_id,
|
|
507
|
+
name=name,
|
|
508
|
+
form_fields=form_fields,
|
|
509
|
+
**extra_body,
|
|
510
|
+
)
|
|
511
|
+
response = await self._client._prepared_request(request)
|
|
512
|
+
return EditTemplate.model_validate(response)
|
|
513
|
+
|
|
514
|
+
async def delete(self, template_id: str) -> None:
|
|
515
|
+
"""
|
|
516
|
+
Delete an edit template.
|
|
517
|
+
|
|
518
|
+
Args:
|
|
519
|
+
template_id: The template ID to delete
|
|
520
|
+
"""
|
|
521
|
+
request = self._prepare_delete(template_id)
|
|
522
|
+
await self._client._prepared_request(request)
|
|
523
|
+
|
|
524
|
+
async def duplicate(
|
|
525
|
+
self,
|
|
526
|
+
template_id: str,
|
|
527
|
+
name: str | None = None,
|
|
528
|
+
**extra_body: Any,
|
|
529
|
+
) -> EditTemplate:
|
|
530
|
+
"""
|
|
531
|
+
Duplicate an existing edit template.
|
|
532
|
+
|
|
533
|
+
Args:
|
|
534
|
+
template_id: The template ID to duplicate
|
|
535
|
+
name: Name for the duplicated template (defaults to "<original> (copy)")
|
|
536
|
+
|
|
537
|
+
Returns:
|
|
538
|
+
EditTemplate: The duplicated template
|
|
539
|
+
"""
|
|
540
|
+
request = self._prepare_duplicate(
|
|
541
|
+
template_id=template_id,
|
|
542
|
+
name=name,
|
|
543
|
+
**extra_body,
|
|
544
|
+
)
|
|
545
|
+
response = await self._client._prepared_request(request)
|
|
546
|
+
return EditTemplate.model_validate(response)
|
|
547
|
+
|
|
548
|
+
async def generate(
|
|
549
|
+
self,
|
|
550
|
+
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
|
551
|
+
model: str = FieldUnset,
|
|
552
|
+
instructions: str | None = FieldUnset,
|
|
553
|
+
**extra_body: Any,
|
|
554
|
+
) -> InferFormSchemaResponse:
|
|
555
|
+
"""
|
|
556
|
+
Infer form schema from a PDF document asynchronously.
|
|
557
|
+
|
|
558
|
+
This method combines computer vision for precise bounding box detection
|
|
559
|
+
with LLM for semantic field naming (key, description) and type classification.
|
|
560
|
+
|
|
561
|
+
Args:
|
|
562
|
+
document: The PDF document to analyze
|
|
563
|
+
model: The LLM model to use for field naming (default: "retab-small")
|
|
564
|
+
instructions: Optional instructions to guide form field detection
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
InferFormSchemaResponse: Response containing:
|
|
568
|
+
- form_schema: The detected form schema
|
|
569
|
+
- annotated_pdf: PDF with bounding boxes for visual verification
|
|
570
|
+
- detection_count: Number of fields detected
|
|
571
|
+
|
|
572
|
+
Note:
|
|
573
|
+
Only PDF documents are supported for form schema inference.
|
|
574
|
+
"""
|
|
575
|
+
request = self._prepare_generate(
|
|
576
|
+
document=document,
|
|
577
|
+
model=model,
|
|
578
|
+
instructions=instructions,
|
|
579
|
+
**extra_body,
|
|
580
|
+
)
|
|
581
|
+
response = await self._client._prepared_request(request)
|
|
582
|
+
return InferFormSchemaResponse.model_validate(response)
|
|
583
|
+
|
|
584
|
+
async def fill(
|
|
585
|
+
self,
|
|
586
|
+
template_id: str,
|
|
587
|
+
instructions: str,
|
|
588
|
+
model: str = FieldUnset,
|
|
589
|
+
**extra_body: Any,
|
|
590
|
+
) -> EditResponse:
|
|
591
|
+
"""
|
|
592
|
+
Fill a PDF form using a pre-defined template asynchronously.
|
|
593
|
+
|
|
594
|
+
This method uses a template's pre-defined form fields to fill a PDF form,
|
|
595
|
+
skipping the field detection step for faster processing.
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
template_id: The template ID to use for filling
|
|
599
|
+
instructions: Instructions describing how to fill the form fields
|
|
600
|
+
model: The LLM model to use for inference (default: "retab-small")
|
|
601
|
+
|
|
602
|
+
Returns:
|
|
603
|
+
EditResponse: Response containing:
|
|
604
|
+
- form_data: List of form fields with filled values
|
|
605
|
+
- filled_document: The filled PDF document as MIMEData
|
|
606
|
+
|
|
607
|
+
Use cases:
|
|
608
|
+
- Batch processing of the same form with different data
|
|
609
|
+
- Faster form filling when field detection is already done
|
|
610
|
+
- Consistent field mapping across multiple fills
|
|
611
|
+
"""
|
|
612
|
+
request = self._prepare_fill(
|
|
613
|
+
template_id=template_id,
|
|
614
|
+
instructions=instructions,
|
|
615
|
+
model=model,
|
|
616
|
+
**extra_body,
|
|
617
|
+
)
|
|
618
|
+
response = await self._client._prepared_request(request)
|
|
619
|
+
return EditResponse.model_validate(response)
|
|
620
|
+
|
retab/types/documents/edit.py
CHANGED
|
@@ -64,7 +64,7 @@ class BaseFormField(BaseModel):
|
|
|
64
64
|
...,
|
|
65
65
|
description="Key of the field. This is used to identify the field in the form data.",
|
|
66
66
|
)
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
|
|
69
69
|
class FormField(BaseFormField):
|
|
70
70
|
"""Single field in the form schema (text input, checkbox, etc.)."""
|
|
@@ -72,8 +72,8 @@ class FormField(BaseFormField):
|
|
|
72
72
|
value: Optional[str] = Field(
|
|
73
73
|
None,
|
|
74
74
|
description=(
|
|
75
|
-
"
|
|
76
|
-
"May be null/None if no value is set."
|
|
75
|
+
"Filled value of the field as text. "
|
|
76
|
+
"May be null/None if no filled value is set."
|
|
77
77
|
),
|
|
78
78
|
)
|
|
79
79
|
|
|
@@ -88,18 +88,6 @@ class FormSchema(BaseModel):
|
|
|
88
88
|
),
|
|
89
89
|
)
|
|
90
90
|
|
|
91
|
-
class FilledFormField(BaseFormField):
|
|
92
|
-
"""Single field in the form schema (text input, checkbox, etc.)."""
|
|
93
|
-
|
|
94
|
-
value: Optional[str] = Field(
|
|
95
|
-
None,
|
|
96
|
-
description=(
|
|
97
|
-
"Filled value of the field as text. "
|
|
98
|
-
"May be null/None if no filled value is set."
|
|
99
|
-
),
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
91
|
class OCRTextElement(BaseModel):
|
|
104
92
|
"""A single OCR-detected text element with its bounding box."""
|
|
105
93
|
|
|
@@ -124,14 +112,6 @@ class InferFormSchemaRequest(BaseModel):
|
|
|
124
112
|
instructions: Optional[str] = Field(default=None, description="Optional instructions to guide form field detection (e.g., which fields to focus on, specific areas to look for)")
|
|
125
113
|
|
|
126
114
|
|
|
127
|
-
class InferFormSchemaResponse(BaseModel):
|
|
128
|
-
"""Response containing the inferred form schema."""
|
|
129
|
-
|
|
130
|
-
form_schema: FormSchema = Field(..., description="The inferred form schema")
|
|
131
|
-
ocr_result: OCRResult = Field(..., description="The OCR results used for inference")
|
|
132
|
-
form_fields_pdf: MIMEData = Field(..., description="PDF with form field bounding boxes")
|
|
133
|
-
|
|
134
|
-
|
|
135
115
|
class EditRequest(BaseModel):
|
|
136
116
|
"""Request for the infer_and_fill_schema endpoint.
|
|
137
117
|
|
|
@@ -141,13 +121,13 @@ class EditRequest(BaseModel):
|
|
|
141
121
|
"""
|
|
142
122
|
document: Optional[MIMEData] = Field(default=None, description="Input document (PDF or DOCX). DOCX files will be converted to PDF. Mutually exclusive with template_id.")
|
|
143
123
|
model: str = Field(default="retab-small", description="LLM model to use for inference")
|
|
144
|
-
|
|
124
|
+
instructions: str = Field(..., description="Instructions to fill the form")
|
|
145
125
|
template_id: Optional[str] = Field(default=None, description="Template ID to use for filling. When provided, uses the template's pre-defined form fields and empty PDF. Only works for PDF documents. Mutually exclusive with document.")
|
|
146
126
|
|
|
147
127
|
class EditResponse(BaseModel):
|
|
148
128
|
"""Response from the fill_form endpoint.
|
|
149
129
|
"""
|
|
150
|
-
form_data: list[
|
|
130
|
+
form_data: list[FormField] = Field(
|
|
151
131
|
...,
|
|
152
132
|
description=(
|
|
153
133
|
"List of form fields (with positions, descriptions, and metadata) "
|
|
@@ -162,3 +142,11 @@ class ProcessOCRRequest(BaseModel):
|
|
|
162
142
|
|
|
163
143
|
document: MIMEData = Field(..., description="Input document (PDF)")
|
|
164
144
|
|
|
145
|
+
|
|
146
|
+
class InferFormSchemaResponse(BaseModel):
|
|
147
|
+
"""Response from form schema inference."""
|
|
148
|
+
|
|
149
|
+
form_schema: FormSchema = Field(..., description="Form schema with detected bounding boxes and field names")
|
|
150
|
+
annotated_pdf: MIMEData = Field(..., description="PDF with form field bounding boxes")
|
|
151
|
+
field_count: int = Field(..., description="Number of fields detected")
|
|
152
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .templates import (
|
|
2
|
+
EditTemplate,
|
|
3
|
+
CreateEditTemplateRequest,
|
|
4
|
+
UpdateEditTemplateRequest,
|
|
5
|
+
DuplicateEditTemplateRequest,
|
|
6
|
+
FillTemplateRequest,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"EditTemplate",
|
|
11
|
+
"CreateEditTemplateRequest",
|
|
12
|
+
"UpdateEditTemplateRequest",
|
|
13
|
+
"DuplicateEditTemplateRequest",
|
|
14
|
+
"FillTemplateRequest",
|
|
15
|
+
]
|
|
16
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Types for edit templates."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
import datetime
|
|
6
|
+
|
|
7
|
+
from ..mime import BaseMIMEData, MIMEData
|
|
8
|
+
from ..documents.edit import FormField
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EditTemplate(BaseModel):
|
|
12
|
+
"""An edit template with pre-defined form fields."""
|
|
13
|
+
|
|
14
|
+
id: str = Field(..., description="Unique identifier of the template")
|
|
15
|
+
name: str = Field(..., description="Name of the template")
|
|
16
|
+
file: BaseMIMEData = Field(..., description="File information for the empty PDF template")
|
|
17
|
+
form_fields: list[FormField] = Field(..., description="List of form fields in the template")
|
|
18
|
+
organization_id: Optional[str] = Field(default=None, description="Organization that owns this template")
|
|
19
|
+
created_at: datetime.datetime = Field(..., description="Timestamp of creation")
|
|
20
|
+
updated_at: datetime.datetime = Field(..., description="Timestamp of last update")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CreateEditTemplateRequest(BaseModel):
|
|
24
|
+
"""Request model for creating an edit template."""
|
|
25
|
+
|
|
26
|
+
name: str = Field(..., description="Name of the template")
|
|
27
|
+
document: MIMEData = Field(..., description="The PDF document to use as the template")
|
|
28
|
+
form_fields: list[FormField] = Field(..., description="List of form fields in the template")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class UpdateEditTemplateRequest(BaseModel):
|
|
32
|
+
"""Request model for updating an edit template."""
|
|
33
|
+
|
|
34
|
+
name: Optional[str] = Field(default=None, description="Name of the template")
|
|
35
|
+
form_fields: Optional[list[FormField]] = Field(default=None, description="List of form fields")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DuplicateEditTemplateRequest(BaseModel):
|
|
39
|
+
"""Request model for duplicating an edit template."""
|
|
40
|
+
|
|
41
|
+
name: Optional[str] = Field(default=None, description="Name for the duplicated template")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class FillTemplateRequest(BaseModel):
|
|
45
|
+
"""Request for the fill endpoint.
|
|
46
|
+
Uses pre-defined form fields from the template (PDF only)
|
|
47
|
+
"""
|
|
48
|
+
model: str = Field(default="retab-small", description="LLM model to use for inference")
|
|
49
|
+
instructions: str = Field(..., description="Instructions to fill the form")
|
|
50
|
+
template_id: str = Field(..., description="Template ID to use for filling. When provided, uses the template's pre-defined form fields and empty PDF. Only works for PDF documents. Mutually exclusive with document.")
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
retab/__init__.py,sha256=s4GawWTRBYz4VY-CyAV5-ZdFtdw8V5oopGIYm9GgdSo,188
|
|
2
2
|
retab/_resource.py,sha256=JfAU4UTa05ugWfbrpO7fsVr_pFewht99NkoIfK6kBQM,577
|
|
3
|
-
retab/client.py,sha256=
|
|
3
|
+
retab/client.py,sha256=VrOzEtZQPR4uydO8QJJYkMOoAiC1TfPbkXmTnatSQ0w,30172
|
|
4
4
|
retab/generate_types.py,sha256=cUu1IX65uU__MHivmEb_PZtzAi8DYsvppZvcY30hj90,8425
|
|
5
5
|
retab/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
retab/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
retab/resources/models.py,sha256=4WidFBnTGZEA65DSn2pLP2SRnCVXkMTw7o_m8xVCFC4,2469
|
|
8
8
|
retab/resources/schemas.py,sha256=rZ6OzfmoYv-mGaRVzvXjO09dD-KxP74mZhOO8sMgcDQ,4632
|
|
9
9
|
retab/resources/documents/__init__.py,sha256=OjXmngFN0RKqO4SI-mJBNzr6Ex6rMxfq0DxaqzP0RQs,89
|
|
10
|
-
retab/resources/documents/client.py,sha256=
|
|
10
|
+
retab/resources/documents/client.py,sha256=0ZOJojT4M9QZ53nheS_vuNZWcnmwTnKx3YqYyJ7_sGY,48912
|
|
11
|
+
retab/resources/edit/__init__.py,sha256=yycIstpTSKsz2qXbrY3Buzd35UDcPWvb5hw6Eb2rLow,69
|
|
12
|
+
retab/resources/edit/client.py,sha256=osWvuKj2SNH6-nQKsWcTYcm3jVENGlwGTvDnT45nDBY,6649
|
|
13
|
+
retab/resources/edit/templates/__init__.py,sha256=n-zA_HXo7iGgeIclSwcsxmSueXJIRMo0iZjk_sax85I,90
|
|
14
|
+
retab/resources/edit/templates/client.py,sha256=Eevzy5JaQmG5-hEshugQvrhgIBAjgZ8ZYZkpBSKEdBQ,19729
|
|
11
15
|
retab/resources/extractions/__init__.py,sha256=2H1ezUG8hI5SmTRy6NFzXdYLOdGFFsFrI60uzkitV20,97
|
|
12
16
|
retab/resources/extractions/client.py,sha256=sEoNjOgX91FTOgoJUV-I1A9A9xl1ciCdPlhYwjhEjbA,11035
|
|
13
17
|
retab/resources/projects/__init__.py,sha256=tPR3_3tr7bsoYd618qmGjnYN2R23PmF5oCFd7Z5_HGY,85
|
|
@@ -25,10 +29,12 @@ retab/types/documents/__init__.py,sha256=t1jXdpYqi-zQMC_9uM0m7eA1hRU0MCROwUx89cc
|
|
|
25
29
|
retab/types/documents/classify.py,sha256=Tb6d_7kuTlWLr7bPn782dHrjtUVBCvXV3o9zm7j2lmE,1128
|
|
26
30
|
retab/types/documents/correct_orientation.py,sha256=e-ivsslI6L6Gl0YkcslXw_DH620xMGEYVp4tdeviXeM,261
|
|
27
31
|
retab/types/documents/create_messages.py,sha256=Uym0SnVUGkyt1C5AOD37BsZ3puyeu_igR6X9SboojfA,7267
|
|
28
|
-
retab/types/documents/edit.py,sha256=
|
|
32
|
+
retab/types/documents/edit.py,sha256=4VK9ed1CF179r8sU4pZXcJhKftorGhul9q-5BlM1Ik4,5606
|
|
29
33
|
retab/types/documents/extract.py,sha256=x_59fm69-icsxxGRgpFd0NN-SLRoMYqbvfCZuG7zyGc,18033
|
|
30
34
|
retab/types/documents/parse.py,sha256=MXe7zh3DusWQhGe0Sr95nPy6cB8DRX8MA4Hmjj_AP7E,1300
|
|
31
35
|
retab/types/documents/split.py,sha256=xRdJ6IpSRAPi_ZtAG2FNqg5A-v5tzfb1QQkW5UfO2pY,1246
|
|
36
|
+
retab/types/edit/__init__.py,sha256=M8hF97h7fX8RP9IsB6qpkw0eyvO0DFQvP6FmWL8caCQ,331
|
|
37
|
+
retab/types/edit/templates.py,sha256=4ndnk-MlJE7roP_YktgxLpRSd68hdwNDWiqAFMy0Ddo,2291
|
|
32
38
|
retab/types/extractions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
39
|
retab/types/extractions/types.py,sha256=mnCYSfJoEKsXN2eG-PrahnnQyR6RDjP5VO9sHC1Opmg,102
|
|
34
40
|
retab/types/projects/__init__.py,sha256=I7P_dems5_LOLgYQ-4Bzt9B6P6jRlQwP-D_9GxRDhVk,155
|
|
@@ -49,7 +55,7 @@ retab/utils/hashing.py,sha256=_BMVUvftOcJav68QL0rLkH2dbhW9RRJPzeGC2akR0fc,757
|
|
|
49
55
|
retab/utils/json_schema.py,sha256=zP4pQLpVHBKWo_abCjb_dU4kA0azhHopd-1TFUgVEvc,20655
|
|
50
56
|
retab/utils/mime.py,sha256=mTP_lqSPttOP5DYJxopiWaeFXrUCPjhwd7y53nCVGO4,6189
|
|
51
57
|
retab/utils/stream_context_managers.py,sha256=gI1gVQSj3nWz6Mvjz7Ix5AiY0g6vSL-c2tPfuP04izo,2314
|
|
52
|
-
retab-0.0.
|
|
53
|
-
retab-0.0.
|
|
54
|
-
retab-0.0.
|
|
55
|
-
retab-0.0.
|
|
58
|
+
retab-0.0.83.dist-info/METADATA,sha256=2fC7uK_AP2G2o6m0-PDITV3A12TB-UMETQ-V51WwxB0,4532
|
|
59
|
+
retab-0.0.83.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
60
|
+
retab-0.0.83.dist-info/top_level.txt,sha256=waQR0EGdhLIQtztoE3AXg7ik5ONQ9q_bsKVpyFuJdq0,6
|
|
61
|
+
retab-0.0.83.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|