Python API Usage
The Generator class is the programmatic entry point to SEED. It is configured
once, then exposes three methods that mirror the command line: generate for a
single document, generate_batch for a diverse set, and generate_packet for a
coordinated multi-document set. Each method returns a typed result.
Installation and setup
Install the package and configure Amazon Bedrock credentials in the environment
(AWS_PROFILE, AWS_REGION) before generating:
pip install seed-data
Create a Generator, specifying the models and acceptance threshold to use:
from seed_data import Generator, ModelConfig
gen = Generator(
models=ModelConfig(data="gpt-oss", doc="gpt-oss", critic="haiku"),
threshold=5,
output_dir="./output",
)
Single document
generate produces one document and returns a GeneratedDoc:
doc = gen.generate("invoice", scenario="Midwest food-distributor invoice, 20 line items")
print(doc.success, doc.verdict, doc.score)
print("PDF: ", doc.pdf_path)
print("Label:", doc.data_json_path)
A GeneratedDoc exposes the rendered PDF, the ground-truth label, and run metadata:
doc.success # bool
doc.pdf_path # rendered PDF
doc.data # ground-truth JSON label (lazy-loaded dict)
doc.data_json_path # path to the label on disk
doc.verdict # "accepted", "rejected", or "error"
doc.score # critic score, 0–10
doc.augmented_path # augmented PDF, when augmentation is enabled
doc.token_usage # {"inputTokens", "outputTokens", "totalTokens"}
doc.error # populated on failure
The data property loads the paired ground-truth label — the exact fields a
document-understanding system should extract from the PDF:
doc = gen.generate("invoice")
if doc.success:
label = doc.data
print(label["invoice_number"], label["total"])
Individual runs can override the generator defaults:
doc = gen.generate("invoice", augment=True) # augment this run only
doc = gen.generate("invoice", verbose=False) # suppress stage progress output
Batch
generate_batch expands a single brief into N distinct scenarios, generates each
concurrently, and returns a BatchResult:
batch = gen.generate_batch(
"fcc-invoice",
count=10,
scenario="CPG brands on local TV stations in the American southwest",
)
print(batch.count_succeeded, "of", batch.count_requested)
for doc in batch.succeeded:
print(doc.doc_id, doc.verdict, doc.pdf_path)
An optional on_document callback reports progress as each document completes:
def on_doc(index, total, doc):
print(f"[{index+1}/{total}] {doc.verdict:9} {doc.pdf_path or doc.error}")
batch = gen.generate_batch(
"fcc-invoice", count=10,
scenario="Political ad invoices during election season on metro-market stations",
on_document=on_doc,
)
A seed makes scenario planning deterministic, producing regression-stable sets:
batch = gen.generate_batch("invoice", count=5, scenario="...", seed=42)
A BatchResult collects every document and provides aggregate accessors:
batch.documents # list[GeneratedDoc], every result in order
batch.succeeded # only the documents that passed
batch.count_succeeded # int
batch.total_tokens # summed across all documents
The results map directly onto an evaluation manifest:
import json
manifest = [
{"pdf": d.pdf_path, "label": d.data_json_path, "verdict": d.verdict}
for d in batch.succeeded
]
json.dump(manifest, open("./output/manifest.json", "w"), indent=2)
Packet
generate_packet produces a coordinated set of related document types that share
context and are merged into one multi-page PDF, returning a PacketResult:
result = gen.generate_packet(
"lending-package",
scenario="First-time homebuyer in Portland, OR, 30-year fixed mortgage",
doc_workers=3,
)
print(result.success, "->", result.merged_pdf)
for s in result.sections:
print(f" {s.document_class:24} pages={s.page_indices} ok={s.success}")
A PacketResult exposes the merged PDF, the shared context, and one section per
sub-document:
result.packet_id
result.merged_pdf # combined multi-page PDF
result.shared_context # the consistent context shared across sections
result.sections # list[SectionResult], one per sub-document
section = result.sections[0]
section.document_class # e.g. "Loan Application"
section.page_indices # pages this section occupies in the merged PDF
section.inference_result # this section's ground-truth data (dict)
section.pdf_path
section.data_json_path
When count is greater than 1, generate_packet returns a list of PacketResult:
results = gen.generate_packet("insurance-claim-packet", count=3,
scenario="Storm-damage claims in coastal Florida")
for r in results:
print(r.packet_id, r.success, len(r.sections), "sections")
Specifying a schema
Every method accepts a schema in three forms — a bundled name, a directory path, or
an in-code Schema:
gen.generate("invoice") # bundled schema name
gen.generate("./my-schemas/invoice") # directory path
gen.generate(my_schema_object) # in-code Schema (below)
An in-code Schema
defines a document type without files on disk, from either a pydantic model or a
raw JSON-Schema dictionary, plus generation guidance:
from pydantic import BaseModel
from seed_data import Schema
class Invoice(BaseModel):
invoice_number: str
vendor: str
total: float
schema = Schema(
name="invoice",
model=Invoice, # or: json_schema={...}
generation_guidance="Totals must equal the sum of line items; US vendors.",
)
doc = gen.generate(schema, scenario="IT consulting services")
# A raw JSON-Schema dictionary instead of a model:
schema = Schema(name="wire", json_schema={
"type": "object",
"properties": {"amount": {"type": "number"}, "recipient": {"type": "string"}},
}, generation_guidance="Domestic wire transfer confirmations.")
An in-code Schema behaves identically across generate, generate_batch, and
generate_packet.
Inferring a schema from documents
Rather than authoring a schema, infer one from real example documents (PDF/PNG/JPEG,
local or s3://). infer_schema returns a Schema that feeds straight into the
generation verbs:
schema = gen.infer_schema(
"./samples/*.pdf", name="invoice",
output_dir="./schemas/invoice", # optional: also write it for review/reuse
)
doc = gen.generate(schema, scenario="Midwest food distributor")
The one-shot convenience methods infer then generate in a single call:
doc = gen.generate_from_samples("./samples/invoice.pdf", name="invoice",
scenario="IT consulting services")
batch = gen.generate_batch_from_samples("s3://bucket/invoices/", name="invoice",
count=10, scenario="Regional US variety")
For a single file containing several different document types concatenated,
infer_packet splits it, infers a schema per segment, and writes a packet
directory ready for generate_packet:
out = gen.infer_packet("./real/lending_package.pdf", name="lending-package",
output_dir="./packets/lending-package",
boundaries="1-3,4,5-8") # boundaries optional
result = gen.generate_packet(out, scenario="First-time homebuyer in Portland, OR")
See Schema from Documents for the full guide.
See also
- CLI Usage — the same capabilities from the command line.
- Schema from Documents — infer schemas from real documents.
GeneratorAPI reference — full method signatures.- Creating a Document Type — authoring a schema.