retab 0.0.43__tar.gz → 0.0.45__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.
- {retab-0.0.43 → retab-0.0.45}/PKG-INFO +2 -2
- {retab-0.0.43 → retab-0.0.45}/README.md +1 -1
- {retab-0.0.43 → retab-0.0.45}/retab/client.py +11 -7
- retab-0.0.45/retab/generate_types.py +180 -0
- retab-0.0.45/retab/resources/deployments/__init__.py +3 -0
- retab-0.0.45/retab/resources/deployments/client.py +148 -0
- retab-0.0.45/retab/resources/projects/__init__.py +3 -0
- {retab-0.0.43/retab/resources/evaluations → retab-0.0.45/retab/resources/projects}/client.py +48 -77
- {retab-0.0.43/retab/resources/evaluations → retab-0.0.45/retab/resources/projects}/documents.py +41 -31
- {retab-0.0.43/retab/resources/evaluations → retab-0.0.45/retab/resources/projects}/iterations.py +12 -12
- {retab-0.0.43 → retab-0.0.45}/retab/types/ai_models.py +1 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/deprecated_evals.py +7 -7
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/base.py +1 -1
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/evaluation.py +1 -1
- {retab-0.0.43/retab/types/evaluations → retab-0.0.45/retab/types/projects}/__init__.py +10 -10
- {retab-0.0.43/retab/types/evaluations → retab-0.0.45/retab/types/projects}/documents.py +3 -3
- {retab-0.0.43/retab/types/evaluations → retab-0.0.45/retab/types/projects}/model.py +16 -19
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/evaluate.py +1 -1
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/object.py +5 -29
- {retab-0.0.43 → retab-0.0.45}/retab/utils/usage/usage.py +0 -1
- {retab-0.0.43 → retab-0.0.45}/retab.egg-info/PKG-INFO +2 -2
- {retab-0.0.43 → retab-0.0.45}/retab.egg-info/SOURCES.txt +11 -8
- {retab-0.0.43 → retab-0.0.45}/setup.py +1 -1
- {retab-0.0.43 → retab-0.0.45}/tests/test_evaluations.py +2 -16
- retab-0.0.43/retab/resources/evaluations/__init__.py +0 -3
- {retab-0.0.43 → retab-0.0.45}/pyproject.toml +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/_resource.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/py.typed +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/consensus/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/consensus/client.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/consensus/completions.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/consensus/completions_stream.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/consensus/responses.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/consensus/responses_stream.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/documents/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/documents/client.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/documents/extractions.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/files.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/finetuning.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/jsonlUtils.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/models.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/openai_example.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/client.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/endpoints.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/links.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/logs.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/mailboxes.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/outlook.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/automations/tests.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/processors/client.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/prompt_optimization.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/schemas.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/secrets/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/secrets/client.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/secrets/external_api_keys.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/secrets/webhook.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/resources/usage.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/cron.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/endpoints.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/links.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/mailboxes.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/outlook.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/automations/webhooks.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/browser_canvas.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/chat.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/completions.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/consensus.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/db/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/db/annotations.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/db/files.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/documents/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/documents/correct_orientation.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/documents/create_messages.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/documents/extractions.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/documents/parse.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/events.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/extractions.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/inference_settings.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/batch_annotation.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/finetune.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/prompt_optimization.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/jobs/webcrawl.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/logs.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/metrics.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/mime.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/modalities.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/pagination.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/predictions.py +0 -0
- {retab-0.0.43/retab/types/evaluations → retab-0.0.45/retab/types/projects}/iterations.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/enhance.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/generate.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/layout.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/schemas/templates.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/secrets/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/secrets/external_api_keys.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/types/standards.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/_model_cards/anthropic.yaml +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/_model_cards/auto.yaml +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/_model_cards/gemini.yaml +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/_model_cards/openai.yaml +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/_model_cards/xai.yaml +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/ai_models.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/benchmarking.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/chat.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/display.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/hashing.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/json_schema.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/mime.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/responses.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/stream_context_managers.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab/utils/usage/__init__.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab.egg-info/dependency_links.txt +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab.egg-info/requires.txt +0 -0
- {retab-0.0.43 → retab-0.0.45}/retab.egg-info/top_level.txt +0 -0
- {retab-0.0.43 → retab-0.0.45}/setup.cfg +0 -0
- {retab-0.0.43 → retab-0.0.45}/tests/test_automations_links.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/tests/test_automations_mailboxes.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/tests/test_documents_api.py +0 -0
- {retab-0.0.43 → retab-0.0.45}/tests/test_preprocessor.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: retab
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.45
|
4
4
|
Summary: Retab official python library
|
5
5
|
Home-page: https://github.com/Retab-dev/retab
|
6
6
|
Author: Retab
|
@@ -67,7 +67,7 @@ Retab solves all the major challenges in document processing with Large Language
|
|
67
67
|
2. **Structured, Schema-driven Extraction**: Get consistent, reliable outputs using schema-based prompt engineering
|
68
68
|
3. **Processors**: Publish a live, stable, shareable document processor.
|
69
69
|
4. **Automations**: Create document processing workflows that can be triggered by events (mailbox, upload link, endpoint, outlook plugin).
|
70
|
-
5. **
|
70
|
+
5. **Projects**: Evaluate the performance of models against annotated datasets
|
71
71
|
6. **Optimizations**: Identify the most used processors and help you finetune models to reduce costs and improve performance
|
72
72
|
|
73
73
|
We are offering you all the software-defined primitives to build your own document processing solutions. We see it as **Stripe** for document processing.
|
@@ -24,7 +24,7 @@ Retab solves all the major challenges in document processing with Large Language
|
|
24
24
|
2. **Structured, Schema-driven Extraction**: Get consistent, reliable outputs using schema-based prompt engineering
|
25
25
|
3. **Processors**: Publish a live, stable, shareable document processor.
|
26
26
|
4. **Automations**: Create document processing workflows that can be triggered by events (mailbox, upload link, endpoint, outlook plugin).
|
27
|
-
5. **
|
27
|
+
5. **Projects**: Evaluate the performance of models against annotated datasets
|
28
28
|
6. **Optimizations**: Identify the most used processors and help you finetune models to reduce costs and improve performance
|
29
29
|
|
30
30
|
We are offering you all the software-defined primitives to build your own document processing solutions. We see it as **Stripe** for document processing.
|
@@ -8,7 +8,7 @@ import backoff.types
|
|
8
8
|
import httpx
|
9
9
|
import truststore
|
10
10
|
|
11
|
-
from .resources import consensus, documents, files, finetuning, models, processors, schemas, secrets, usage,
|
11
|
+
from .resources import consensus, deployments, documents, files, finetuning, models, processors, schemas, secrets, usage, projects
|
12
12
|
from .types.standards import PreparedRequest, FieldUnset
|
13
13
|
|
14
14
|
|
@@ -135,7 +135,7 @@ class Retab(BaseRetab):
|
|
135
135
|
"""Synchronous client for interacting with the Retab API.
|
136
136
|
|
137
137
|
This client provides synchronous access to all Retab API resources including files, fine-tuning,
|
138
|
-
prompt optimization, documents, models,
|
138
|
+
prompt optimization, documents, models, processors, deployments, and schemas.
|
139
139
|
|
140
140
|
Args:
|
141
141
|
api_key (str, optional): Retab API key. If not provided, will look for RETAB_API_KEY env variable.
|
@@ -151,7 +151,8 @@ class Retab(BaseRetab):
|
|
151
151
|
prompt_optimization: Access to prompt optimization operations
|
152
152
|
documents: Access to document operations
|
153
153
|
models: Access to model operations
|
154
|
-
|
154
|
+
processors: Access to processor operations
|
155
|
+
deployments: Access to deployment operations
|
155
156
|
schemas: Access to schema operations
|
156
157
|
responses: Access to responses API (OpenAI Responses API compatible interface)
|
157
158
|
"""
|
@@ -175,13 +176,14 @@ class Retab(BaseRetab):
|
|
175
176
|
)
|
176
177
|
|
177
178
|
self.client = httpx.Client(timeout=self.timeout)
|
178
|
-
self.
|
179
|
+
self.projects = projects.Projects(client=self)
|
179
180
|
self.files = files.Files(client=self)
|
180
181
|
self.fine_tuning = finetuning.FineTuning(client=self)
|
181
182
|
self.documents = documents.Documents(client=self)
|
182
183
|
self.models = models.Models(client=self)
|
183
184
|
self.schemas = schemas.Schemas(client=self)
|
184
185
|
self.processors = processors.Processors(client=self)
|
186
|
+
self.deployments = deployments.Deployments(client=self)
|
185
187
|
self.secrets = secrets.Secrets(client=self)
|
186
188
|
self.usage = usage.Usage(client=self)
|
187
189
|
self.consensus = consensus.Consensus(client=self)
|
@@ -395,7 +397,7 @@ class AsyncRetab(BaseRetab):
|
|
395
397
|
"""Asynchronous client for interacting with the Retab API.
|
396
398
|
|
397
399
|
This client provides asynchronous access to all Retab API resources including files, fine-tuning,
|
398
|
-
prompt optimization, documents, models,
|
400
|
+
prompt optimization, documents, models, processors, deployments, and schemas.
|
399
401
|
|
400
402
|
Args:
|
401
403
|
api_key (str, optional): Retab API key. If not provided, will look for RETAB_API_KEY env variable.
|
@@ -413,7 +415,8 @@ class AsyncRetab(BaseRetab):
|
|
413
415
|
prompt_optimization: Access to asynchronous prompt optimization operations
|
414
416
|
documents: Access to asynchronous document operations
|
415
417
|
models: Access to asynchronous model operations
|
416
|
-
|
418
|
+
processors: Access to asynchronous processor operations
|
419
|
+
deployments: Access to asynchronous deployment operations
|
417
420
|
schemas: Access to asynchronous schema operations
|
418
421
|
responses: Access to responses API (OpenAI Responses API compatible interface)
|
419
422
|
"""
|
@@ -438,13 +441,14 @@ class AsyncRetab(BaseRetab):
|
|
438
441
|
|
439
442
|
self.client = httpx.AsyncClient(timeout=self.timeout)
|
440
443
|
|
441
|
-
self.
|
444
|
+
self.projects = projects.AsyncProjects(client=self)
|
442
445
|
self.files = files.AsyncFiles(client=self)
|
443
446
|
self.fine_tuning = finetuning.AsyncFineTuning(client=self)
|
444
447
|
self.documents = documents.AsyncDocuments(client=self)
|
445
448
|
self.models = models.AsyncModels(client=self)
|
446
449
|
self.schemas = schemas.AsyncSchemas(client=self)
|
447
450
|
self.processors = processors.AsyncProcessors(client=self)
|
451
|
+
self.deployments = deployments.AsyncDeployments(client=self)
|
448
452
|
self.secrets = secrets.AsyncSecrets(client=self)
|
449
453
|
self.usage = usage.AsyncUsage(client=self)
|
450
454
|
self.consensus = consensus.AsyncConsensus(client=self)
|
@@ -0,0 +1,180 @@
|
|
1
|
+
import collections.abc
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
import types
|
5
|
+
import typing
|
6
|
+
import enum
|
7
|
+
import sys
|
8
|
+
import inspect
|
9
|
+
from datetime import datetime, date
|
10
|
+
from typing import Any, Type, get_args, get_origin, Union, Literal, is_typeddict
|
11
|
+
from typing_extensions import is_typeddict as is_typeddict_ext
|
12
|
+
import typing_extensions
|
13
|
+
from pydantic_core import PydanticUndefined
|
14
|
+
from pydantic import BaseModel, EmailStr
|
15
|
+
import PIL.Image
|
16
|
+
|
17
|
+
to_compile: list[tuple[str, Type, bool]] = []
|
18
|
+
|
19
|
+
def is_base_model(field_type: Type) -> bool:
|
20
|
+
return getattr(field_type, "__name__", None) in ["BaseModel", "GenericModel", "ConfigDict", "Generic"]
|
21
|
+
|
22
|
+
def type_to_zod(field_type: Any, put_names: bool = True, ts: bool = False) -> str:
|
23
|
+
origin = get_origin(field_type) or field_type
|
24
|
+
optional = False
|
25
|
+
|
26
|
+
def make_union(args):
|
27
|
+
return args[0] if len(args) <= 1 else "z.union([" + ", ".join(args) + "])"
|
28
|
+
|
29
|
+
def make_ts_union(args):
|
30
|
+
return args[0] if len(args) <= 1 else " | ".join(args)
|
31
|
+
|
32
|
+
if isinstance(field_type, typing.ForwardRef):
|
33
|
+
return type_to_zod(typing._eval_type(field_type, globals(), locals(), []), ts=ts)
|
34
|
+
elif origin is typing.Annotated or origin is typing.Required or origin is typing_extensions.Required:
|
35
|
+
return type_to_zod(get_args(field_type)[0], put_names, ts=ts)
|
36
|
+
if origin is Union or origin is types.UnionType:
|
37
|
+
args = [x for x in get_args(field_type)]
|
38
|
+
if types.NoneType in args:
|
39
|
+
args.remove(types.NoneType)
|
40
|
+
optional = True
|
41
|
+
typename = make_union([type_to_zod(x) for x in args])
|
42
|
+
ts_typename = make_ts_union([type_to_zod(x, ts=True) for x in args])
|
43
|
+
elif issubclass(origin, BaseModel) or is_typeddict(origin) or is_typeddict_ext(origin):
|
44
|
+
if put_names:
|
45
|
+
typename = "Z" + origin.__name__
|
46
|
+
ts_typename = origin.__name__
|
47
|
+
to_compile.append((origin.__name__, field_type, True))
|
48
|
+
else:
|
49
|
+
excluded_fields = set()
|
50
|
+
typename = "z.object({\n"
|
51
|
+
ts_typename = "{\n"
|
52
|
+
props = [(n, f.annotation, f.default) for n, f in origin.model_fields.items()] if issubclass(origin, BaseModel) else \
|
53
|
+
[(n, f, PydanticUndefined) for n, f in origin.__annotations__.items()]
|
54
|
+
|
55
|
+
for field_name, field, default in props:
|
56
|
+
if field_name in excluded_fields:
|
57
|
+
continue
|
58
|
+
ts_compiled = type_to_zod(field, ts=True)
|
59
|
+
default_str = ""
|
60
|
+
if default is not PydanticUndefined and default is not None:
|
61
|
+
if isinstance(default, BaseModel):
|
62
|
+
default_str = f".default({json.dumps(default.model_dump(mode="json", exclude_unset=True))})"
|
63
|
+
else:
|
64
|
+
default_str = f".default({json.dumps(default)})"
|
65
|
+
typename += f" {field_name}: {type_to_zod(field)}{default_str},\n"
|
66
|
+
ts_typename += f" {field_name}{"?" if ts_compiled.endswith(" | undefined") or default is not PydanticUndefined else ""}: {ts_compiled},\n"
|
67
|
+
typename += "})"
|
68
|
+
ts_typename += "}"
|
69
|
+
|
70
|
+
based = origin.__bases__
|
71
|
+
for i in range(0, len(based)):
|
72
|
+
if is_base_model(based[i]) or based[i] is dict:
|
73
|
+
break
|
74
|
+
if issubclass(based[i], BaseModel):
|
75
|
+
excluded_fields.update(based[i].model_fields.keys())
|
76
|
+
typename += ".merge(Z" + based[i].__name__ + ".schema)"
|
77
|
+
ts_typename += " & " + based[i].__name__
|
78
|
+
elif origin is list or origin is typing.List or origin is collections.abc.Sequence or origin is collections.abc.Iterable:
|
79
|
+
typename = "z.array(" + type_to_zod(get_args(field_type)[0]) + ")"
|
80
|
+
ts_typename = "Array<" + type_to_zod(get_args(field_type)[0], ts=True) + ">"
|
81
|
+
elif origin is tuple:
|
82
|
+
args = get_args(field_type)
|
83
|
+
typename = "z.tuple([" + ", ".join([type_to_zod(x) for x in args]) + "])"
|
84
|
+
ts_typename = "[" + ", ".join([type_to_zod(x, ts=True) for x in args]) + "]"
|
85
|
+
elif origin is dict:
|
86
|
+
if len(get_args(field_type)) == 2:
|
87
|
+
typename = "z.record(" + type_to_zod(get_args(field_type)[0]) + ", " + type_to_zod(get_args(field_type)[1]) + ")"
|
88
|
+
ts_typename = "{[key: " + type_to_zod(get_args(field_type)[0], ts=True) + "]: " + type_to_zod(get_args(field_type)[1], ts=True) + "}"
|
89
|
+
else:
|
90
|
+
typename = "z.record(z.any())"
|
91
|
+
ts_typename = "{[key: string]: any}"
|
92
|
+
elif origin is Literal:
|
93
|
+
typename = make_union(["z.literal(" + json.dumps(x) + ")" for x in get_args(field_type)])
|
94
|
+
ts_typename = make_ts_union([json.dumps(x) for x in get_args(field_type)])
|
95
|
+
elif isinstance(field_type, typing.TypeVar):
|
96
|
+
typename = "z.any()"
|
97
|
+
ts_typename = "any"
|
98
|
+
elif isinstance(field_type, type) and issubclass(field_type, enum.Enum):
|
99
|
+
typename = "z.any()"
|
100
|
+
ts_typename = "any"
|
101
|
+
elif field_type is str or field_type is date or field_type is datetime:
|
102
|
+
typename = "z.string()"
|
103
|
+
ts_typename = "string"
|
104
|
+
elif field_type is int or field_type is float:
|
105
|
+
typename = "z.number()"
|
106
|
+
ts_typename = "number"
|
107
|
+
elif field_type is bool:
|
108
|
+
typename = "z.boolean()"
|
109
|
+
ts_typename = "boolean"
|
110
|
+
elif field_type is typing.Any:
|
111
|
+
typename = "z.any()"
|
112
|
+
ts_typename = "any"
|
113
|
+
elif field_type is bytes or field_type is PIL.Image.Image or field_type is typing.BinaryIO or origin is typing.IO or origin is typing_extensions.IO:
|
114
|
+
typename = "z.instanceof(Uint8Array)"
|
115
|
+
ts_typename = "Uint8Array"
|
116
|
+
elif field_type is EmailStr:
|
117
|
+
typename = "z.string().email()"
|
118
|
+
ts_typename = "string"
|
119
|
+
elif field_type is os.PathLike:
|
120
|
+
typename = "z.string()"
|
121
|
+
ts_typename = "string"
|
122
|
+
elif field_type is object:
|
123
|
+
typename = "z.object({}).passthrough()"
|
124
|
+
ts_typename = "object"
|
125
|
+
else:
|
126
|
+
raise ValueError(f"Unsupported type: {field_type} ({origin})")
|
127
|
+
if ts:
|
128
|
+
return ts_typename if not optional else ts_typename + " | null | undefined"
|
129
|
+
else:
|
130
|
+
return typename if not optional else typename + ".nullable().optional()"
|
131
|
+
|
132
|
+
|
133
|
+
# SET of names of python builtin types starting with a capital
|
134
|
+
builtin_types = {
|
135
|
+
"Any",
|
136
|
+
"BaseModel",
|
137
|
+
"NoneType",
|
138
|
+
"Literal",
|
139
|
+
"Union",
|
140
|
+
"List",
|
141
|
+
"Sequence",
|
142
|
+
"ConfigDict",
|
143
|
+
"Optional",
|
144
|
+
}
|
145
|
+
|
146
|
+
if __name__ == "__main__":
|
147
|
+
modules = []
|
148
|
+
for root, dirs, files in os.walk("retab/types"):
|
149
|
+
for module in files:
|
150
|
+
if module[-3:] != '.py':
|
151
|
+
continue
|
152
|
+
full_name = os.path.join(root, module[:-3]).replace(os.path.sep, '.')
|
153
|
+
__import__(full_name, locals(), globals())
|
154
|
+
modules.append(full_name)
|
155
|
+
|
156
|
+
|
157
|
+
for module_name in modules:
|
158
|
+
for name, obj in inspect.getmembers(sys.modules[module_name]):
|
159
|
+
if name[0] != name[0].lower() and name not in builtin_types:
|
160
|
+
to_compile.append((name, obj, False))
|
161
|
+
|
162
|
+
print("import * as z from 'zod';\n")
|
163
|
+
|
164
|
+
defined = {}
|
165
|
+
while len(to_compile) > 0:
|
166
|
+
name, model, necessary = to_compile.pop(0)
|
167
|
+
if name in defined: continue
|
168
|
+
defined[name] = True
|
169
|
+
try:
|
170
|
+
compiled = type_to_zod(model, False)
|
171
|
+
compiled_ts = type_to_zod(model, False, ts=True)
|
172
|
+
except Exception as e:
|
173
|
+
if not necessary:
|
174
|
+
print(f"Skipping {name} {model} due to error: {e}", file=sys.stderr)
|
175
|
+
continue
|
176
|
+
print(f"Error compiling {name} {model}", file=sys.stderr)
|
177
|
+
raise e
|
178
|
+
print("export const Z" + name + " = z.lazy(() => " + compiled + ");")
|
179
|
+
print("export type " + name + " = z.infer<typeof Z" + name + ">;\n")
|
180
|
+
|
@@ -0,0 +1,148 @@
|
|
1
|
+
import base64
|
2
|
+
from io import IOBase
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Any, List
|
5
|
+
|
6
|
+
import PIL.Image
|
7
|
+
from pydantic import HttpUrl
|
8
|
+
from ..._resource import AsyncAPIResource, SyncAPIResource
|
9
|
+
from ...utils.mime import MIMEData, prepare_mime_document
|
10
|
+
from ...types.documents.extractions import RetabParsedChatCompletion
|
11
|
+
from ...types.standards import PreparedRequest
|
12
|
+
|
13
|
+
|
14
|
+
class DeploymentsMixin:
|
15
|
+
def prepare_extract(
|
16
|
+
self,
|
17
|
+
project_id: str,
|
18
|
+
iteration_id: str,
|
19
|
+
document: Path | str | bytes | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
20
|
+
documents: list[Path | str | bytes | IOBase | MIMEData | PIL.Image.Image | HttpUrl] | None = None,
|
21
|
+
temperature: float | None = None,
|
22
|
+
seed: int | None = None,
|
23
|
+
store: bool = True,
|
24
|
+
) -> PreparedRequest:
|
25
|
+
"""Prepare a request to extract documents from a deployment.
|
26
|
+
|
27
|
+
Args:
|
28
|
+
project_id: ID of the project
|
29
|
+
iteration_id: ID of the iteration
|
30
|
+
document: Single document to process (mutually exclusive with documents)
|
31
|
+
documents: List of documents to process (mutually exclusive with document)
|
32
|
+
temperature: Optional temperature override
|
33
|
+
seed: Optional seed for reproducibility
|
34
|
+
store: Whether to store the results
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
PreparedRequest: The prepared request
|
38
|
+
"""
|
39
|
+
# Validate that either document or documents is provided, but not both
|
40
|
+
if not document and not documents:
|
41
|
+
raise ValueError("Either 'document' or 'documents' must be provided")
|
42
|
+
|
43
|
+
if document and documents:
|
44
|
+
raise ValueError("Provide either 'document' (single) or 'documents' (multiple), not both")
|
45
|
+
|
46
|
+
# Prepare form data parameters
|
47
|
+
form_data = {
|
48
|
+
"temperature": temperature,
|
49
|
+
"seed": seed,
|
50
|
+
"store": store,
|
51
|
+
}
|
52
|
+
# Remove None values
|
53
|
+
form_data = {k: v for k, v in form_data.items() if v is not None}
|
54
|
+
|
55
|
+
# Prepare files for upload
|
56
|
+
files = {}
|
57
|
+
if document:
|
58
|
+
# Convert document to MIMEData if needed
|
59
|
+
mime_document = prepare_mime_document(document)
|
60
|
+
# Single document upload
|
61
|
+
files["document"] = (mime_document.filename, base64.b64decode(mime_document.content), mime_document.mime_type)
|
62
|
+
elif documents:
|
63
|
+
# Multiple documents upload - httpx supports multiple files with same field name using a list
|
64
|
+
files_list = []
|
65
|
+
for doc in documents:
|
66
|
+
# Convert each document to MIMEData if needed
|
67
|
+
mime_doc = prepare_mime_document(doc)
|
68
|
+
files_list.append(
|
69
|
+
(
|
70
|
+
"documents", # field name
|
71
|
+
(mime_doc.filename, base64.b64decode(mime_doc.content), mime_doc.mime_type),
|
72
|
+
)
|
73
|
+
)
|
74
|
+
files = files_list
|
75
|
+
|
76
|
+
url = f"/v1/deployments/extract/{project_id}/{iteration_id}"
|
77
|
+
|
78
|
+
return PreparedRequest(method="POST", url=url, form_data=form_data, files=files)
|
79
|
+
|
80
|
+
|
81
|
+
class Deployments(SyncAPIResource, DeploymentsMixin):
|
82
|
+
"""Deployments API wrapper for managing deployment configurations"""
|
83
|
+
|
84
|
+
def __init__(self, client: Any) -> None:
|
85
|
+
super().__init__(client=client)
|
86
|
+
|
87
|
+
def extract(
|
88
|
+
self,
|
89
|
+
project_id: str,
|
90
|
+
iteration_id: str,
|
91
|
+
document: Path | str | bytes | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
92
|
+
documents: List[Path | str | bytes | IOBase | MIMEData | PIL.Image.Image | HttpUrl] | None = None,
|
93
|
+
temperature: float | None = None,
|
94
|
+
seed: int | None = None,
|
95
|
+
store: bool = True,
|
96
|
+
) -> RetabParsedChatCompletion:
|
97
|
+
"""Extract documents from a deployment.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
project_id: ID of the project
|
101
|
+
iteration_id: ID of the iteration
|
102
|
+
document: Single document to process (mutually exclusive with documents)
|
103
|
+
documents: List of documents to process (mutually exclusive with document)
|
104
|
+
temperature: Optional temperature override
|
105
|
+
seed: Optional seed for reproducibility
|
106
|
+
store: Whether to store the results
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
RetabParsedChatCompletion: The processing result
|
110
|
+
"""
|
111
|
+
request = self.prepare_extract(project_id=project_id, iteration_id=iteration_id, document=document, documents=documents, temperature=temperature, seed=seed, store=store)
|
112
|
+
response = self._client._prepared_request(request)
|
113
|
+
return RetabParsedChatCompletion.model_validate(response)
|
114
|
+
|
115
|
+
|
116
|
+
class AsyncDeployments(AsyncAPIResource, DeploymentsMixin):
|
117
|
+
"""Async Deployments API wrapper for managing deployment configurations"""
|
118
|
+
|
119
|
+
def __init__(self, client: Any) -> None:
|
120
|
+
super().__init__(client=client)
|
121
|
+
|
122
|
+
async def extract(
|
123
|
+
self,
|
124
|
+
project_id: str,
|
125
|
+
iteration_id: str,
|
126
|
+
document: Path | str | bytes | IOBase | MIMEData | PIL.Image.Image | HttpUrl | None = None,
|
127
|
+
documents: List[Path | str | bytes | IOBase | MIMEData | PIL.Image.Image | HttpUrl] | None = None,
|
128
|
+
temperature: float | None = None,
|
129
|
+
seed: int | None = None,
|
130
|
+
store: bool = True,
|
131
|
+
) -> RetabParsedChatCompletion:
|
132
|
+
"""Extract documents from a deployment.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
project_id: ID of the project
|
136
|
+
iteration_id: ID of the iteration
|
137
|
+
document: Single document to process (mutually exclusive with documents)
|
138
|
+
documents: List of documents to process (mutually exclusive with document)
|
139
|
+
temperature: Optional temperature override
|
140
|
+
seed: Optional seed for reproducibility
|
141
|
+
store: Whether to store the results
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
RetabParsedChatCompletion: The processing result
|
145
|
+
"""
|
146
|
+
request = self.prepare_extract(project_id=project_id, iteration_id=iteration_id, document=document, documents=documents, temperature=temperature, seed=seed, store=store)
|
147
|
+
response = await self._client._prepared_request(request)
|
148
|
+
return RetabParsedChatCompletion.model_validate(response)
|