Split a law review article into sections and extract any part
A law review article is long and highly structured: an abstract, a table of contents, and dozens of numbered sections, often across a hundred or more pages. Pulling one piece, say the abstract, first means finding where it lives before you can read it. With Reducto you parse the whole article once, split it into its constituent parts, and then run a targeted extract against only the pages that hold what you want. Three endpoints, one pipeline: Parse turns the PDF into clean structured text, Split maps the article into its sections, and Extract pulls the exact field you asked for with citations back to the source.
What you'll build
Law review article (PDF, often 100+ pages)
- Parse: clean, structured full text
- Split: locate the abstract, table of contents, and every section by page
- Extract: pull the abstract's exact text from just those pages, with citations
Setup
Grab an API key from studio.reducto.ai -> API Keys -> Create new API key, then set it and install the SDK:
bashexport REDUCTO_API_KEY="your-api-key-here" pip install reducto
Use any long, structured legal article as a PDF. No template setup or per-document tuning required. Need a sample? In Reducto Studio, open the Law Review Article template, where an example article and this exact pipeline are already set up. Run it there for a no-code preview, or download the PDF from the pipeline to follow the API steps below.
Step 1: Parse the article
First parse the full article so the later steps have clean, structured text to work from. table_output_format: "html" keeps any tables intact, and chunking is disabled so the whole article comes back as one document that Split can map end to end.
pythonfrom pathlib import Path from reducto import Reducto client = Reducto() upload = client.upload(file=Path("law_review_article.pdf")) parse_result = client.parse.run( input=upload.file_id, formatting={ "table_output_format": "html", }, settings={ "extraction_mode": "hybrid", "ocr_system": "standard", }, spreadsheet={ "clustering": "accurate", "split_large_tables": {"enabled": True, "size": 50}, }, retrieval={ "chunking": {"chunk_mode": "disabled"}, # keep the whole article in one result }, ) print(f"Parsed {parse_result.usage.num_pages} pages. Review it in Studio: {parse_result.studio_link}")
Step 2: Split the article into its parts
Point Split at the Step 1 parse job so it reuses that work instead of re-parsing. Each entry in split_description is a part to find; add a partition_key to break one part into repeated sub-parts, the way Sections is divided by section name. split_rules gives the model context about the document, and table_cutoff: "truncate" keeps a long table from bleeding across a boundary. Split returns each part with the pages it spans. These three parts fit a typical law review article; edit split_description to match whatever structure your own documents use.
pythonsplit_result = client.split.run( input=f"jobid://{parse_result.job_id}", # reuse the Step 1 parse, no re-parsing split_description=[ {"name": "Abstract", "description": "The abstract of the article."}, { "name": "Sections", "description": "The sections of the article, subdivided by the name of the section.", "partition_key": "Section Name", }, {"name": "Table of Contents", "description": "The table of contents of this article."}, ], split_rules="You are reading a legal article, and your task is to find all of the constituent sections of the article.", settings={"table_cutoff": "truncate"}, ) for part in split_result.result.splits: print(f"{part.name}: pages {part.pages}")
Step 3: Extract the abstract from the pages Split found
Now run Extract against only the abstract's pages instead of the whole article. Pull the page range straight from the Split result so nothing is hardcoded, point Extract at those pages, and turn on citations so every value traces back to its exact location in the document.
pythonabstract = next( (part for part in split_result.result.splits if part.name == "Abstract"), None, ) if abstract is None: raise ValueError("Split found no 'Abstract' part. Adjust split_description to match your document.") abstract_pages = abstract.pages schema = { "type": "object", "properties": { "abstract": { "type": "string", "description": ( "The abstract in its full text. Extract exactly what is in the " "document in full, without summarizing or truncating." ), }, }, "required": ["abstract"], } result = client.extract.run( input=upload.file_id, parsing={ "settings": {"page_range": abstract_pages}, # only the pages Split flagged as the abstract }, instructions={ "schema": schema, "system_prompt": "Get the abstract from this section, without summarizing or truncating.", }, settings={ "citations": {"enabled": True}, }, )
With citations on, each field comes back wrapped as an object with a value and a citations list (the source text, its page and bounding box, and a confidence score). Read the text with field["value"] and its source with field["citations"].
pythondata = result.result abstract = data["abstract"] print(abstract["value"]) print(f"cited on page {abstract['citations'][0]['bbox']['page']}, confidence {abstract['citations'][0]['confidence']}")
To pull a different part of the article, look up its pages by name from split_result (for example "Table of Contents" or any section name) and pass a schema describing the fields you want. Everything else in the Extract call stays the same, so one pattern covers every part Split returns.
Prefer no code?
Want to see it run first? In Reducto Studio, open the Law Review Article template, where an example article and the full Parse -> Split -> Extract pipeline are already set up, and press Run. To build your own, upload an article, add the parse, split, and extract steps, and Run. Review the split parts and extracted fields side by side with the source, then Deploy the pipeline as an API endpoint for the rest of your documents.
Where this goes next
You now have a pipeline that locates and pulls any part of a long legal document. Extend it from here:
- Push accuracy further with Deep Extract: turn on
deep_extractfor dense or ambiguous sections where an agentic pass raises accuracy. - Sort first with Classify: route law review articles, briefs, and opinions to the right pipeline before you split them.
- Hand clean data to an LLM or agent: the split sections and cited fields drop straight into a legal RAG index or a research agent.
- Deploy the whole flow: wire Parse, Split, and Extract into one endpoint so every new article runs the same way.