Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions datalab_sdk/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ def process_documents(
mode: str = "fast",
# Extract-specific
page_schema: Optional[str] = None,
schema_id: Optional[str] = None,
schema_version: Optional[int] = None,
checkpoint_id: Optional[str] = None,
# Segment-specific
segmentation_schema: Optional[str] = None,
Expand Down Expand Up @@ -323,7 +325,9 @@ def process_documents(
)
elif method == "extract":
options = ExtractOptions(
page_schema=page_schema or "",
page_schema=page_schema,
schema_id=schema_id,
schema_version=schema_version,
checkpoint_id=checkpoint_id,
mode=mode,
output_format=output_format or "markdown",
Expand Down Expand Up @@ -450,14 +454,18 @@ def convert(

@click.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("--page_schema", required=True, help="JSON schema for structured extraction (must contain 'properties' key)")
@click.option("--page_schema", default=None, help="Inline JSON schema for structured extraction (must contain 'properties' key). Mutually exclusive with --schema_id.")
@click.option("--schema_id", default=None, help="Saved schema ID (e.g. sch_k8Hx9mP2nQ4v). Mutually exclusive with --page_schema.")
@click.option("--schema_version", default=None, type=int, help="Version of the saved schema to use. Only valid with --schema_id.")
@click.option("--checkpoint_id", help="Checkpoint ID from a previous convert (skips re-parsing)")
@click.option("--format", "output_format", default="markdown", type=click.Choice(["markdown", "html", "json", "chunks"]), help="Output format")
@click.option("--mode", type=click.Choice(["fast", "balanced", "accurate"]), default="fast", help="Processing mode")
@common_options
def extract(
path: str,
page_schema: str,
page_schema: Optional[str],
schema_id: Optional[str],
schema_version: Optional[int],
checkpoint_id: Optional[str],
output_format: str,
mode: str,
Expand All @@ -473,6 +481,12 @@ def extract(
poll_interval: int,
):
"""Extract structured data from documents using a JSON schema"""
if not page_schema and not schema_id:
raise click.UsageError("Either --page_schema or --schema_id must be provided.")
if page_schema and schema_id:
raise click.UsageError("--page_schema and --schema_id are mutually exclusive.")
if schema_version is not None and not schema_id:
raise click.UsageError("--schema_version can only be used with --schema_id.")
process_documents(
path=path,
method="extract",
Expand All @@ -489,6 +503,8 @@ def extract(
output_format=output_format,
mode=mode,
page_schema=page_schema,
schema_id=schema_id,
schema_version=schema_version,
checkpoint_id=checkpoint_id,
)

Expand Down
10 changes: 9 additions & 1 deletion datalab_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ def _build_conversion_result(self, result_data: Dict[str, Any], default_format:
checkpoint_id=result_data.get("checkpoint_id"),
versions=result_data.get("versions"),
parse_quality_score=result_data.get("parse_quality_score"),
extraction_score_average=result_data.get("extraction_score_average"),
runtime=result_data.get("runtime"),
cost_breakdown=result_data.get("cost_breakdown"),
evaluation=result_data.get("evaluation"),
Expand Down Expand Up @@ -536,7 +537,14 @@ async def extract(
raise ValueError(f"Directory does not exist: {resolved_stream_response_to.parent}")

if options is None:
raise ValueError("options must be provided with page_schema")
raise ValueError("options must be provided with either page_schema or schema_id")

if not options.page_schema and not options.schema_id:
raise ValueError("Either options.page_schema or options.schema_id must be provided")
if options.page_schema and options.schema_id:
raise ValueError("Provide either options.page_schema or options.schema_id, not both")
if options.schema_version is not None and not options.schema_id:
raise ValueError("options.schema_version can only be used with options.schema_id")

has_file = file_path is not None or file_url is not None
has_checkpoint = options.checkpoint_id is not None
Expand Down
12 changes: 10 additions & 2 deletions datalab_sdk/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ConvertOptions(ProcessingOptions):
add_block_ids: bool = False # add block IDs to HTML output
include_markdown_in_chunks: bool = False # include markdown field in chunks/JSON output
token_efficient_markdown: bool = False # optimize markdown for LLM token usage
eval_rubric_id: Optional[int] = None # run evaluation against a saved rubric after conversion

def to_form_data(self) -> Dict[str, Any]:
"""Convert to form data format for API requests"""
Expand All @@ -76,9 +77,15 @@ def to_form_data(self) -> Dict[str, Any]:

@dataclass
class ExtractOptions(ProcessingOptions):
"""Options for structured data extraction via /extract endpoint"""
"""Options for structured data extraction via /extract endpoint

page_schema: str = "" # Required - JSON schema with 'properties' key
Provide either page_schema (inline JSON schema) or schema_id (saved schema reference),
but not both. schema_version can only be used together with schema_id.
"""

page_schema: Optional[str] = None # Inline JSON schema with 'properties' key
schema_id: Optional[str] = None # Saved schema ID (e.g. sch_k8Hx9mP2nQ4v); mutually exclusive with page_schema
schema_version: Optional[int] = None # Version of the saved schema; only valid with schema_id
checkpoint_id: Optional[str] = None # From previous /convert with save_checkpoint=true
mode: str = "fast" # fast, balanced, accurate
output_format: str = "markdown" # markdown, json, html, chunks
Expand Down Expand Up @@ -169,6 +176,7 @@ class ConversionResult:
checkpoint_id: Optional[str] = None
versions: Optional[Union[Dict[str, Any], str]] = None
parse_quality_score: Optional[float] = None
extraction_score_average: Optional[float] = None # Average confidence score (1-5) across extracted fields
runtime: Optional[float] = None
cost_breakdown: Optional[Dict[str, Any]] = None
evaluation: Optional[Dict[str, Any]] = None # Evaluation results when run_eval=true
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading