Multi-Dimensional Extraction
The mde resource submits and manages multi-dimensional extraction jobs. It is available via client.mde.
Multi-dimensional extraction is for table-like or entity-centric outputs: you define a schema with columns, then the AI returns rows and cells that match that schema.
import asyncio
from biolevate import BiolevateClient, EntityColumnInput, EntitySchemaInput
async def main():
async with BiolevateClient(
base_url="https://<api-domain>",
token="<your-pat>",
) as client:
schema = EntitySchemaInput(
name="compounds",
description="Compounds studied in the source documents and their administered doses",
columns=[
EntityColumnInput(
key="compound",
label="Compound",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_IDENTIFIER",
description="Compound or treatment name",
is_row_key=True,
),
EntityColumnInput(
key="dose",
label="Dose",
type="ENTITY_COLUMN_TYPE_FLOAT",
role="ENTITY_COLUMN_ROLE_VALUE",
),
],
)
job = await client.mde.create_job(
schema=schema,
file_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
)
print(f"Job created: {job.job_id} (status: {job.status})")
asyncio.run(main())
Schema Fields
EntitySchemaInput describes the table to extract. All fields are optional.
| Field | Type | Description |
|---|---|---|
name | str | None | Short, machine-friendly name of the entity schema (for example, compounds) |
description | str | None | Natural-language description of what the table represents, giving the AI extra context |
columns | list[EntityColumnInput] | None | The columns to extract for each row |
A concise description helps the backend understand the intent of the whole schema, complementing the per-column label, description, and role. Leave it empty if the name and columns are already self-explanatory.
Methods
create_job()
Submit a new multi-dimensional extraction job. Define the entity schema and target documents by file_ids, collection_ids, or both.
from biolevate import EntityColumnInput, EntitySchemaInput
schema = EntitySchemaInput(
name="study_interventions",
description="Interventions evaluated per study population and their effect sizes",
columns=[
EntityColumnInput(
key="intervention",
label="Intervention",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_IDENTIFIER",
is_row_key=True,
),
EntityColumnInput(
key="population",
label="Population",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_GROUP",
),
EntityColumnInput(
key="effect_size",
label="Effect Size",
type="ENTITY_COLUMN_TYPE_FLOAT",
role="ENTITY_COLUMN_ROLE_VALUE",
),
],
)
job = await client.mde.create_job(
schema=schema,
file_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
)
| Parameter | Type | Default | Description |
|---|---|---|---|
schema | EntitySchemaInput | — | Entity schema describing columns to extract |
file_ids | list[str] | None | None | UUIDs of individual EliseFiles to process |
collection_ids | list[str] | None | None | UUIDs of Collections to process |
config | JobLaunchConfig | None | None | Job launch behaviour, e.g. JobLaunchConfig(skip_unindexed_files=True) |
See Common Patterns: Job Launch Config for details on config.
Returns Job
Raises AuthenticationError, APIError
Column Roles
EntityColumnInput.role is optional. It describes the semantic function of a column, beyond type and is_row_key, and helps the backend interpret how columns relate to each other.
If you are unsure, omit role or set it to ENTITY_COLUMN_ROLE_UNSPECIFIED. The backend can infer intent from key, label, description, type, and is_row_key.
EntityColumnInput(
key="custom_field",
label="Custom field",
description="A custom field where the semantic role is not known",
# role omitted intentionally
)
Available Role Values
| Role | Meaning | Examples |
|---|---|---|
ENTITY_COLUMN_ROLE_UNSPECIFIED | Unknown or intentionally unspecified role. The backend infers from the rest of the schema. | custom_field, misc_value |
ENTITY_COLUMN_ROLE_IDENTIFIER | Stable ID, code, acronym, accession number, DOI, NCT ID, PMID, or registry ID. Helps recognize entities. | study_id, nct_id, doi, pmid, accession_number |
ENTITY_COLUMN_ROLE_LABEL | Human-readable name or display label. Not necessarily stable or unique. | study_name, intervention_name, endpoint_name, biomarker_name |
ENTITY_COLUMN_ROLE_GROUP | Group, category, arm, cohort, population, subgroup, sex, age group, or disease severity. Scopes values. | treatment_arm, dose_group, cohort, population, sex, age_group |
ENTITY_COLUMN_ROLE_TIMEPOINT | Visit, timepoint, cycle, follow-up window, day, month, or week. Aligns repeated measurements over time. | week, visit, timepoint, cycle, month, assessment_window |
ENTITY_COLUMN_ROLE_VALUE | Measured value: score, percentage, count, ratio, p-value, number, or textual result. Usually not a row key. | response_rate, mean_change, event_count, hazard_ratio, p_value, score |
ENTITY_COLUMN_ROLE_UNIT | Unit, scale, or symbol separated from the value. Helps interpret adjacent values. | unit, dose_unit, measurement_unit, rate_unit, scale |
ENTITY_COLUMN_ROLE_DEFINITION | Definition of a concept, endpoint, criterion, threshold, or inclusion rule. | endpoint_definition, response_definition, inclusion_criteria, event_definition |
ENTITY_COLUMN_ROLE_COMMENT | Note, caveat, footnote, extraction comment, or additional context. | comment, note, footnote, caveat, additional_context |
Role Examples
from biolevate import EntityColumnInput, EntitySchemaInput
schema = EntitySchemaInput(
name="ClinicalOutcome",
columns=[
EntityColumnInput(
key="trial_id",
label="Trial ID",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_IDENTIFIER",
is_row_key=True,
),
EntityColumnInput(
key="treatment_arm",
label="Treatment arm",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_GROUP",
is_row_key=True,
),
EntityColumnInput(
key="week",
label="Week",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_TIMEPOINT",
is_row_key=True,
),
EntityColumnInput(
key="response_rate",
label="Response rate (%)",
type="ENTITY_COLUMN_TYPE_FLOAT",
role="ENTITY_COLUMN_ROLE_VALUE",
is_row_key=False,
),
EntityColumnInput(
key="unit",
label="Unit",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_UNIT",
is_row_key=False,
),
EntityColumnInput(
key="response_definition",
label="Response definition",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_DEFINITION",
description="How response was defined in the source document",
),
EntityColumnInput(
key="note",
label="Note",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_COMMENT",
),
],
)
Practical Rule of Thumb
- Measured result ->
ENTITY_COLUMN_ROLE_VALUE - "For which group?" ->
ENTITY_COLUMN_ROLE_GROUP - "When?" ->
ENTITY_COLUMN_ROLE_TIMEPOINT - Stable ID or code ->
ENTITY_COLUMN_ROLE_IDENTIFIER - Human-readable name ->
ENTITY_COLUMN_ROLE_LABEL - Unit or scale ->
ENTITY_COLUMN_ROLE_UNIT - Concept or criterion definition ->
ENTITY_COLUMN_ROLE_DEFINITION - Note or caveat ->
ENTITY_COLUMN_ROLE_COMMENT - Not sure -> omit
roleor useENTITY_COLUMN_ROLE_UNSPECIFIED
get_job()
Get the current status of a multi-dimensional extraction job. Poll until status is SUCCESS, FAILED, or ABORTED.
job = await client.mde.get_job(job_id)
print(f"Status: {job.status}")
| Parameter | Type | Description |
|---|---|---|
job_id | str | UUID of the multi-dimensional extraction job |
Returns Job
Raises NotFoundError, AuthenticationError, APIError
list_jobs()
List all multi-dimensional extraction jobs for the current user.
page = await client.mde.list_jobs(page=0, page_size=20)
for job in page.data:
print(f"{job.job_id}: {job.status}")
| Parameter | Type | Default | Description |
|---|---|---|---|
page | int | 0 | Page number (0-based) |
page_size | int | 20 | Number of jobs per page |
sort_by | str | None | None | Field to sort by |
sort_order | str | "asc" | Sort direction |
Returns JobPage
Raises AuthenticationError, APIError
get_job_outputs()
Retrieve extracted rows and cells from a completed job.
outputs = await client.mde.get_job_outputs(job_id)
entity_extraction = outputs.entity_extraction
for row in entity_extraction.rows or []:
for cell in row.cells or []:
print(f"{cell.column_key}: {cell.value}")
| Parameter | Type | Description |
|---|---|---|
job_id | str | UUID of the multi-dimensional extraction job |
Returns MDEJobOutputs
Raises NotFoundError, AuthenticationError, APIError
get_job_inputs()
Retrieve the original file targets and entity schema submitted to the job.
inputs = await client.mde.get_job_inputs(job_id)
print(inputs.var_schema.name)
The generated Python model exposes the JSON field schema as var_schema to avoid conflicting with Pydantic's schema() method.
| Parameter | Type | Description |
|---|---|---|
job_id | str | UUID of the multi-dimensional extraction job |
Returns MDEJobInputs
Raises NotFoundError, AuthenticationError, APIError
get_job_annotations()
Retrieve source annotations for all extracted rows and cells.
annotations = await client.mde.get_job_annotations(job_id)
annotation_map = {a.id.id: a for a in annotations}
| Parameter | Type | Description |
|---|---|---|
job_id | str | UUID of the multi-dimensional extraction job |
Returns list[Annotation]
Raises NotFoundError, AuthenticationError, APIError
Full Example — Create, Poll, and Retrieve Rows
import asyncio
from biolevate import BiolevateClient, EntityColumnInput, EntitySchemaInput
TERMINAL_STATUSES = {"SUCCESS", "FAILED", "ABORTED"}
async def main():
async with BiolevateClient(
base_url="https://<api-domain>",
token="<your-pat>",
) as client:
schema = EntitySchemaInput(
name="compounds",
description="Compounds studied in the source documents and their administered doses",
columns=[
EntityColumnInput(
key="compound",
label="Compound",
type="ENTITY_COLUMN_TYPE_STRING",
role="ENTITY_COLUMN_ROLE_IDENTIFIER",
is_row_key=True,
),
EntityColumnInput(
key="dose",
label="Dose",
type="ENTITY_COLUMN_TYPE_FLOAT",
role="ENTITY_COLUMN_ROLE_VALUE",
),
],
)
job = await client.mde.create_job(schema=schema, file_ids=["a1b2c3d4-e5f6-7890-abcd-ef1234567890"])
print(f"Job created: {job.job_id}")
while True:
job = await client.mde.get_job(job.job_id)
if job.status in TERMINAL_STATUSES:
break
await asyncio.sleep(3)
if job.status == "SUCCESS":
outputs = await client.mde.get_job_outputs(job.job_id)
for row in outputs.entity_extraction.rows or []:
print({cell.column_key: cell.value for cell in row.cells or []})
asyncio.run(main())
Next Steps
- Extraction — extract a fixed list of typed metadata fields
- Annotations guide — resolve source passages referenced by results
- Multi-Dimensional Extraction guide — the same workflow with REST examples