Session — Create and manage extraction sessions.
mx_session(), mx_profile(), show_steps(), remove_step()
Detection — Scan a PDF for table locations.
detect_tables(), detect_tables_quietly(), locate_area()
Table extraction — Pull tables out of PDF pages.
select_table(), select_table_docling(), select_table_llm(), stack_pages(), stack_tables(), merge_tables(), pdf_table()
Metadata extraction — Extract individual fields and structured records.
select_item(), select_items_batch(), select_struct(), struct_to_df(), show_items(), update_item(), update_llm_schema(), suggest_schema()
LLM configuration — Configure the LLM provider at session or global level.
mx_configure_llm()
Cleaning — Rename, cast, filter, and reshape extracted tables.
rename_columns(), cast_types(), filter_rows(), add_column(), split_column(), split_column_df(), fill_down(), clean_numbers(), clean_numbers_df()
Inspection — Preview and visualise extracted data.
preview(), preview_all(), view_in_pdf()
Macros — Save, load, and replay extraction workflows.
save_macro(), load_macro(), mx_replay(), mx_replay_batch(), validate_macro()
Comparison — Diff macro outputs across two PDFs.
diff_replay(), detail()
Validation — Validate table structure and values.
validate_table(), show_validations()
Export — Write extracted data to files.
export_csv(), export_excel(), export_json()
Testing — Snapshot-test macro outputs in CI.
test_macro(), test_extraction(), expect_table_snapshot()
Shiny — Embed macrox in a Shiny application.
mx_app(), macrox_ui(), macrox_server()
Python backends — Set up optional ML and NLP engines.
setup_docling(), close_docling(), setup_gliner(), close_gliner()
-- A --
add_column()
-- C --
cast_types()
clean_numbers()
clean_numbers_df()
close_docling()
close_gliner()
-- D --
detail()
detect_tables()
detect_tables_quietly()
diff_replay()
-- E --
expect_table_snapshot()
export_csv()
export_excel()
export_json()
-- F --
fill_down()
filter_rows()
-- L --
load_macro()
locate_area()
-- M --
macrox_server()
macrox_ui()
merge_tables()
mx_app()
mx_configure_llm()
mx_profile()
mx_replay()
mx_replay_batch()
mx_session()
-- P --
pdf_table()
preview()
preview_all()
-- R --
remove_step()
rename_columns()
-- S --
save_macro()
select_item()
select_items_batch()
select_struct()
select_table()
select_table_docling()
select_table_llm()
setup_docling()
setup_gliner()
show_items()
show_steps()
show_validations()
split_column()
split_column_df()
stack_pages()
stack_tables()
struct_to_df()
suggest_schema()
-- T --
test_extraction()
test_macro()
-- U --
update_item()
update_llm_schema()
-- V --
validate_macro()
validate_table()
view_in_pdf()
Add a derived column to an extracted table
add_column(sess, table, name, expr)
sess |
A |
table |
Character label of the target table. |
name |
Name of the new column. |
expr |
R expression (as a string) evaluated against the data frame,
e.g. |
sess invisibly (step is recorded).
Cast column types in an extracted table
cast_types(sess, table, types)
sess |
A |
table |
Character label of the target table. |
types |
Named character vector: |
sess invisibly (step is recorded).
Strips thousands separators, currency symbols, and parenthetical negatives;
maps sentinel strings to NA; optionally coerces columns to numeric.
clean_numbers(
sess,
table,
cols = NULL,
currency = c("£", "$", "€", "¥"),
na_strings = c("-", "—", "n/a", "na", ""),
negative_parens = TRUE,
convert = TRUE
)
sess |
A |
table |
Character label of the target table. |
cols |
Character vector of column names to process. |
currency |
Character vector of currency symbols to strip. |
na_strings |
Strings that should become |
negative_parens |
If |
convert |
If |
sess invisibly (step is recorded).
The data-frame counterpart of clean_numbers(): it takes a data frame and
returns a data frame, with no session and no recorded step. Use it when the
table is already in hand, for example inside a script or a pipeline.
clean_numbers_df(
df,
cols = NULL,
currency = c("£", "$", "€", "¥"),
na_strings = c("-", "—", "n/a", "na", ""),
negative_parens = TRUE,
convert = TRUE
)
df |
A data frame. |
cols |
Character vector of column names to process. |
currency |
Character vector of currency symbols to strip. |
na_strings |
Strings that should become |
negative_parens |
If |
convert |
If |
df with the selected columns cleaned.
Frees the in-memory cache of converted PDF documents. Call this when you are done extracting tables to reduce memory usage.
close_docling()
Invisible NULL.
Unload the GLiNER2 model from memory
close_gliner()
NULL invisibly.
Returns a data frame of every cell that changed between the two replays, with
columns row, col, ref, new, and delta (numeric difference, or NA
for non-numeric columns).
detail(x, ...)
x |
A |
... |
Passed to methods. For |
A data frame with one row per changed cell.
Scans the specified pages of the PDF for tables and prints a summary. This function is NOT recorded in the macro — it is for exploration only.
detect_tables(
sess,
pages = NULL,
method = c("lattice", "stream", "docling"),
min_rows = 1L,
max_header_chars = 40L
)
sess |
A |
pages |
Integer vector of pages to scan. Defaults to all pages. |
method |
Extraction method: |
min_rows |
Minimum number of data rows a table must have to be shown
and stored. Default |
max_header_chars |
Maximum character length allowed for the first
column name before the table is flagged as a likely chart/figure and
skipped. Default |
Results are stored in sess$detect as a list of
list(page, index, df) entries that can be passed directly to
select_table() via table_index. When method = "docling", pages are
converted in a single pass and the results are cached so that subsequent
select_table_docling() calls on those pages run instantly.
sess invisibly (not recorded).
Like detect_tables() but returns a named list silently. Intended for
agent/programmatic use.
detect_tables_quietly(
path,
pages = NULL,
method = c("lattice", "stream", "docling"),
min_rows = 1L,
max_header_chars = 40L
)
path |
Path to a PDF file. |
pages |
Integer vector of pages to scan. Defaults to all pages. |
method |
Extraction method: |
min_rows |
Minimum data rows required (default |
max_header_chars |
Maximum first-column name length before skipping
(default |
Named list: page number (character) → list of data frames.
Replays the same macro against two files and returns a structured diff
showing added, removed, and changed tables. For changed tables the diff
includes per-column numeric delta statistics. Use detail() on the result
to inspect which cells changed.
diff_replay(
file1,
file2,
macro,
macro_path = ".",
params = list(),
params2 = NULL
)
file1 |
Path to the reference PDF. |
file2 |
Path to the new PDF. |
macro |
Macro name, path to a |
macro_path |
Directory for macro lookup (default |
params |
Named list of parameter values applied to both replays (e.g.
|
params2 |
Named list of parameter values for |
A macrox_diff object. Print gives a summary; detail() drills
into a single table.
Wraps testthat::expect_snapshot() to lock in the printed representation of
a table stored in a session. On first run the snapshot is written to
tests/testthat/_snaps/; subsequent runs compare against that baseline.
expect_table_snapshot(sess, label = NULL, variant = NULL)
sess |
A |
label |
Character label of the table to snapshot. Ignored when |
variant |
Optional variant string passed to
|
Must be called inside a testthat test (i.e., within test_that()).
The result of expect_snapshot(), invisibly.
Writes one .csv per table into dir. Existing files are overwritten.
export_csv(sess, dir = ".", tables = NULL)
sess |
A |
dir |
Directory to write into (created if it doesn't exist). |
tables |
Character vector of table labels to export. Default: all tables. |
Named character vector of output file paths, invisibly.
Writes one worksheet per table. Requires the writexl or openxlsx
package.
export_excel(sess, path = "macrox_tables.xlsx", tables = NULL)
sess |
A |
path |
Output |
tables |
Character vector of table labels to include. Default: all. |
path invisibly.
Combines extracted items (document metadata) and tables into a single self-describing JSON document. Suitable for API ingestion, database loading, and RAG pipelines.
export_json(sess, path = NULL, pretty = TRUE, include_steps = FALSE)
sess |
A |
path |
File path to write the JSON. |
pretty |
Logical; pretty-print the JSON (default |
include_steps |
Include the recorded step list in the output (default
|
The JSON string, invisibly.
Fills each blank or NA cell downward from the last non-blank value.
Useful when merged header cells in government PDFs leave empty values in
rows below the merged cell boundary.
fill_down(sess, table, cols = NULL)
sess |
A |
table |
Character label of the target table. |
cols |
Character vector of column names to fill. |
sess invisibly (step is recorded).
Remove rows matching an expression
filter_rows(sess, table, exclude_where)
sess |
A |
table |
Character label of the target table. |
exclude_where |
Character string expression evaluated against the data
frame columns. Rows where the expression is |
sess invisibly (step is recorded).
Load a YAML macro
load_macro(name, path = ".")
name |
Macro name (stem) or full path to a |
path |
Directory to look in when |
The list of step definitions. If the macro declares parameters, a
params attribute is attached — inspect with attr(steps, "params").
Opens a click-and-drag gadget (via tabulapdf::locate_areas) to capture
bounding box coordinates. Returns a named c(top, left, bottom, right)
vector suitable for passing directly to select_table().
locate_area(sess, page = 1)
sess |
A |
page |
Page number to display (default 1). |
Named numeric vector c(top, left, bottom, right), invisibly.
Shiny module server for PDF table extraction
macrox_server(id)
id |
Module namespace ID (must match |
A list with two reactives: tables (named list of data frames) and
steps (list of step definitions).
Provides a split-pane interface: PDF viewer on the left, live extracted table on the right. Transforms (rename, type-cast, filter) open in modal dialogs so both panes remain visible.
macrox_ui(id, title = "PDF · Table Extractor", height = "600px")
id |
Module namespace ID. |
title |
Card title shown in the header (default |
height |
Height of the PDF image pane (default |
A bslib card UI element.
Wraps base::merge() and records the step so it replays automatically.
merge_tables(
sess,
label,
left,
right,
by,
all = FALSE,
all.x = FALSE,
all.y = FALSE
)
sess |
A |
label |
Label for the merged output table. |
left |
Label of the left table. |
right |
Label of the right table. |
by |
Character vector of column names to join on. |
all |
Logical; |
all.x |
Left join when |
all.y |
Right join when |
sess invisibly (step is recorded).
Opens a full Shiny application for interactive PDF table extraction, cleaning, and export. The app is self-contained — no existing session or macro is required.
mx_app(viewer = c("browser", "dialog", "pane"))
viewer |
Where to display the app:
|
Called for its side-effect. Returns invisibly when the app is closed.
Sets a single LLM configuration for the session so that
select_table_llm() and select_item() can be
called without specifying provider, model, or chat on
every call. The configured chat object is cloned for each extraction so its
conversation history is never shared between calls.
mx_configure_llm(
sess,
chat = NULL,
provider = getOption("macrox.llm.provider", "anthropic"),
model = getOption("macrox.llm.model", NULL),
base_url = NULL,
system = NULL
)
sess |
A |
chat |
An existing |
provider |
Provider name (default |
model |
Model name. |
base_url |
Base URL for |
system |
System prompt passed to the provider constructor. |
sess invisibly.
sess <- mx_session("report.pdf")
# Use Anthropic with ellmer's default model (Claude Sonnet 5 in ellmer 0.5.0)
sess |> mx_configure_llm(provider = "anthropic")
sess |> select_table_llm("my_table", page = 5)
sess |> select_item("date", prompt = "Publication date")
# Or pin to a specific model for reproducibility
sess |> mx_configure_llm(provider = "anthropic", model = "claude-opus-4-8")
# Or pass a fully configured chat object for maximum control
chat <- ellmer::chat_anthropic(
model = "claude-sonnet-5",
system = "Extract data exactly as shown."
)
sess |> mx_configure_llm(chat = chat)
Returns a structured machine-readable description of the PDF's tables and surrounding text context. Pass the result to an LLM to generate a macro.
mx_profile(path, pages = NULL, method = "lattice", context_lines = 3)
path |
Path to a PDF file. |
pages |
Integer vector of pages to scan. Defaults to all pages (capped at 60). |
method |
Extraction method: |
context_lines |
Number of text lines above/below each table's header row to include as context (default 3). |
A macrox_profile list.
Replay a macro against a new PDF file
mx_replay(file, macro, macro_path = ".", params = list())
file |
Path to the PDF file. |
macro |
Either a macro name / path (character) or a step list returned
by |
macro_path |
Directory to look for the macro file (default |
params |
Named list of parameter values for parameterised macros, e.g.
|
Named list of extracted data frames.
Replay a macro across multiple PDF files
mx_replay_batch(
files,
macro,
macro_path = ".",
params = list(),
.progress = TRUE,
.parallel = FALSE
)
files |
Character vector of PDF file paths. |
macro |
Macro name, path, or step list (see |
macro_path |
Directory for macro lookup (default |
params |
Named list of parameter values passed to each |
.progress |
Show file-level progress messages (default TRUE). |
.parallel |
If |
Named list (file basenames) of table lists. Files that fail are NULL.
Creates a session object that holds the PDF path, extracted tables, and a running log of every recorded step.
mx_session(path = NULL)
path |
Path to a PDF file, or an image file (PNG, JPG, TIFF, BMP, GIF,
WEBP). Image files are automatically converted to PDF; only
|
An invisible macrox_session environment.
Reads one table from one page of a PDF with the word-position (bbox)
engine and returns it as a data frame. It needs no session and records no
step, which makes it convenient in scripts and pipelines.
pdf_table(
path,
page,
area = NULL,
header_rows = 1L,
row_tol = NULL,
col_gap = NULL
)
path |
Path to a PDF file. |
page |
Page number. |
area |
Optional named numeric vector |
header_rows |
Number of header rows. Several rows are joined into a single column name. |
row_tol, col_gap |
Optional tuning for row clustering and column gap
detection. |
A data frame.
pdf_table("report.pdf", page = 9, header_rows = 4)
Preview one extracted table
preview(sess, table, n = 6)
sess |
A |
table |
Character label of the table to preview. |
n |
Number of rows to show (default 6). |
sess invisibly. # not recorded
Preview all extracted tables with numeric totals
preview_all(sess, n = 6)
sess |
A |
n |
Number of rows to show per table (default 6). |
sess invisibly. # not recorded
Remove a recorded step by index
remove_step(sess, index)
sess |
A |
index |
Integer index of the step to remove (see |
sess invisibly.
Rename columns in an extracted table
rename_columns(sess, table, mapping)
sess |
A |
table |
Character label of the target table. |
mapping |
Named character vector: |
sess invisibly (step is recorded).
Save the session's recorded steps as a YAML macro
save_macro(sess, name, path = ".", overwrite = FALSE, params = NULL)
sess |
A |
name |
Macro name (used as the filename stem). |
path |
Directory to write the |
overwrite |
Logical; overwrite an existing file? (default FALSE) |
params |
Optional parameter declarations for parameterised macros.
Accepts a named character vector |
The output file path, invisibly.
Extracts a single structured value from a PDF using either an LLM or a
local GLiNER2 model. Results are stored in sess$items[[label]] and
recorded as a step.
select_item(
sess,
label,
prompt,
cast = NULL,
page = NULL,
area = NULL,
backend = c("llm", "gliner"),
chat = NULL,
provider = getOption("macrox.llm.provider", "anthropic"),
model = getOption("macrox.llm.model", NULL),
base_url = NULL,
dpi = 120L,
gliner_model = "fastino/gliner2-base-v1",
all_matches = FALSE
)
sess |
A |
label |
Character label for the item (e.g. |
prompt |
Description of the field to extract. For the LLM backend
this is the full instruction; for GLiNER it is the field description
passed alongside |
cast |
Optional type to cast the returned string to: |
page |
Page number. For |
area |
Named |
backend |
Extraction backend: |
chat |
An existing |
provider |
LLM provider (default |
model |
Model name. Only used when |
base_url |
Base URL for |
dpi |
Render resolution when |
gliner_model |
GLiNER2 model name (HuggingFace repo). Only used when
|
all_matches |
Logical; only used when |
sess invisibly (step is recorded).
# LLM backend (default)
sess |> select_item("invoice_number",
prompt = "Extract the invoice ID or reference number.")
# GLiNER backend — local, no API key needed
setup_gliner()
sess |> select_item("invoice_number",
prompt = "Invoice ID or reference number",
backend = "gliner")
# GLiNER on a specific page
sess |> select_item("total_amount",
prompt = "Grand total amount payable",
page = 1L,
cast = "numeric",
backend = "gliner")
Runs a single GLiNER2 inference call to extract several named fields from a
PDF, which is significantly faster than calling select_item() once per
field. Each field is recorded as a separate select_item step so macros
replay with the standard select_item mechanism.
select_items_batch(
sess,
items,
page = NULL,
cast = NULL,
gliner_model = "fastino/gliner2-base-v1",
all_matches = FALSE
)
sess |
A |
items |
Named character vector: names are field labels, values are
natural-language prompts describing the field.
E.g. |
page |
Page number to extract from. |
cast |
Named character vector of cast types keyed by label. Unlisted
fields default to |
gliner_model |
GLiNER2 model identifier. Default
|
all_matches |
If |
GLiNER2 can return multiple occurrences of the same entity type when they
are present in the text; select_items_batch surfaces the first match per
field (the same behaviour as select_item()).
sess invisibly (one select_item step recorded per field).
Uses GLiNER2's extract_json to extract a structured entity schema
(multiple fields, optional list fields, multiple records) from a PDF page.
Results are stored as a data frame in sess$tables[[label]], identical to
tabulapdf / LLM table extraction — downstream steps and exports work
unchanged.
select_struct(
sess,
label,
entity = label,
fields,
list_fields = character(0),
enum_fields = character(0),
page = 1L,
gliner_model = "fastino/gliner2-base-v1"
)
sess |
A |
label |
Table label to store results under. |
entity |
Entity type name used in the GLiNER2 schema. Defaults to
|
fields |
Named character vector: |
list_fields |
Character vector of field names that may contain multiple
values (GLiNER2 |
enum_fields |
Named character vector of enumerated field types:
|
page |
Integer or integer vector of pages to extract from. Multiple
pages use a single |
gliner_model |
GLiNER2 model identifier.
Default |
sess invisibly (step recorded).
Three selection modes: by page + index, by bounding box (area), or by
fuzzy caption match (label_match). These can be mixed across different
tables in the same session.
select_table(
sess,
label,
page = NULL,
table_index = 1,
area = NULL,
label_match = NULL,
method = c("lattice", "stream", "bbox"),
header_rows = 1,
fuzzy_method = "jw",
max_dist = 0.2,
row_tol = NULL,
col_gap = NULL
)
sess |
A |
label |
Character label for the extracted table. |
page |
Page number (integer). Required unless |
table_index |
Which table on the page (1-based, tabulapdf methods only). Default 1. |
area |
Named numeric vector |
label_match |
Text caption to fuzzy-search across all pages. |
method |
Extraction engine:
|
header_rows |
Number of header rows to merge (default 1). Use 2+ for multi-row spanning headers. |
fuzzy_method |
stringdist method for caption matching (default |
max_dist |
Maximum normalised distance for a fuzzy match (default 0.2). |
row_tol |
|
col_gap |
|
sess invisibly (step is recorded).
Converts the PDF page using Docling's ML layout pipeline and returns a
clean data frame. Works fully offline after the initial one-time model
download; handles scanned PDFs and complex layouts where bbox fails.
select_table_docling(sess, label, page, table_index = 1L)
sess |
A |
label |
Character label for the extracted table. |
page |
Page number (integer). |
table_index |
Which table to use when multiple are detected on the page (default 1). |
Docling converts the target page the first time it is called and caches
the result in the Python session, so repeated calls for different tables
on the same page do not re-run the conversion pipeline. Call
close_docling() to release the cache when done.
sess invisibly (step is recorded).
Renders the PDF page (optionally cropped to area), sends it to an LLM
with a structured schema, and returns a clean data frame. Good for
multi-level headers, tables embedded in mixed-content pages, and any
situation where positional extraction fails.
select_table_llm(
sess,
label,
page,
area = NULL,
chat = NULL,
provider = getOption("macrox.llm.provider", "anthropic"),
model = getOption("macrox.llm.model", NULL),
base_url = NULL,
schema = NULL,
prompt = NULL,
dpi = 150L,
header_rows = 1L,
mode = c("structured", "page"),
table_index = 1L
)
sess |
A |
label |
Character label for the extracted table. |
page |
Page number (integer). |
area |
Named numeric vector |
chat |
An existing |
provider |
Name of an |
model |
Model name. |
base_url |
Base URL for |
schema |
Named character vector mapping column names to R types:
|
prompt |
Optional extra instructions appended to the base prompt,
e.g. |
dpi |
Render resolution for the page image (default 150). |
header_rows |
Number of header rows. When > 1 the prompt asks the
LLM to flatten them with |
mode |
Extraction mode:
|
table_index |
When |
Requires the ellmer package (install.packages("ellmer")) and an API
key for the chosen provider set as an environment variable
(ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY).
sess invisibly (step is recorded).
Creates (or reuses) a Python environment and installs the docling package.
Run once and restart R before calling select_table_docling().
setup_docling(envname = "r-macrox", pip_options = character(0))
envname |
Name of the Python environment (default |
pip_options |
Extra pip flags, e.g.
|
On the first extraction call Docling downloads its ML models (~2-3 GB) and caches them locally. Subsequent calls are fully offline.
Invisible NULL.
Installs the gliner2 Python package and pre-loads the requested model so
it is ready for select_item() calls with backend = "gliner".
setup_gliner(
model = "fastino/gliner2-base-v1",
envname = "r-macrox",
pip_options = character(0)
)
model |
Pre-trained model identifier (HuggingFace repo). Defaults to
the 205M base model |
envname |
Python virtual environment name (default |
pip_options |
Additional pip install options (character vector). |
NULL invisibly.
Show all extracted items
show_items(sess)
sess |
A |
sess invisibly. # not recorded
Prints a numbered list of all steps in the session, with flagged steps highlighted.
show_steps(sess)
sess |
A |
sess invisibly.
Prints a summary of every validate_table() result stored in the session.
show_validations(sess)
sess |
A |
sess invisibly. # not recorded
Splits each cell in col on sep (a regex) and stores the resulting
pieces in new columns named by into. The original column is removed
unless keep = TRUE. Cells with fewer pieces than length(into) are
padded with NA; cells with more are truncated.
split_column(sess, table, col, into, sep = "\\s+", keep = FALSE)
sess |
A |
table |
Character label of the target table. |
col |
Name of the column to split. |
into |
Character vector of names for the new columns. |
sep |
Regex separator (default |
keep |
If |
sess invisibly (step is recorded).
The data-frame counterpart of split_column(): it takes a data frame and
returns a data frame, with no session and no recorded step.
split_column_df(df, col, into, sep = "\\s+", keep = FALSE)
df |
A data frame. |
col |
Name of the column to split. |
into |
Character vector of names for the new columns. |
sep |
Regex separator (default |
keep |
If |
df with col replaced (or, with keep = TRUE, followed) by the
new columns named in into.
Extracts a table from each page in pages and row-binds them into a single
data frame. Supports all extraction engines including "llm".
stack_pages(
sess,
label,
pages,
area = NULL,
method = c("bbox", "lattice", "stream", "llm"),
chat = NULL,
provider = getOption("macrox.llm.provider", "anthropic"),
model = getOption("macrox.llm.model", NULL),
base_url = NULL,
schema = NULL,
prompt = NULL,
dpi = 150L,
mode = c("structured", "page"),
table_index = 1L,
header_rows = 1L,
header_match = TRUE,
row_tol = NULL,
col_gap = NULL
)
sess |
A |
label |
Character label for the combined table. |
pages |
Integer vector of page numbers to extract and stack (minimum 2). |
area |
Named |
method |
Extraction engine: |
chat |
An existing |
provider |
LLM provider (LLM method only, default |
model |
Model name (LLM method only). |
base_url |
Base URL for |
schema |
Named character vector of column types, e.g.
|
prompt |
Extra instructions appended to the base prompt (LLM only). |
dpi |
Render resolution for page images (LLM only, default 150). |
mode |
LLM extraction mode: |
table_index |
Which table to pick when |
header_rows |
Number of header rows (non-LLM methods, default 1). |
header_match |
Logical (non-LLM methods, default |
row_tol |
|
col_gap |
|
For "bbox", "lattice", and "stream": repeated header rows are handled
automatically when header_match = TRUE (default) — the header is consumed
as column names on each page and dropped from the data. Set
header_match = FALSE when pages 2+ start directly with data.
For "llm": the model returns schema-defined columns directly so there are
no repeated headers to consume; header_match is ignored. Supply schema
for best accuracy and consistent column names across pages.
sess invisibly (step is recorded).
Useful after batch replay to combine monthly or regional tables that share the same schema.
stack_tables(sess, label, tables, .fill = FALSE)
sess |
A |
label |
Label for the combined output table. |
tables |
Character vector of existing table labels to stack. |
.fill |
Fill missing columns with |
sess invisibly (step is recorded).
Takes the raw GLiNER2 records stored by select_struct() (which include
per-field confidence scores) and converts them to a data frame stored in
sess$tables[[label]]. Optionally filters out low-confidence records.
struct_to_df(sess, label, min_confidence = NULL)
sess |
A |
label |
Label matching a prior |
min_confidence |
Numeric in |
sess invisibly (step recorded).
Inspects values in each column and returns a named character vector of type
specs compatible with cast_types(). Useful as a starting point before
calling cast_types() or providing a schema to select_table_llm().
suggest_schema(sess, label)
sess |
A |
label |
Character label of the table to inspect. |
Named character vector of type specs (invisibly).
The R-Core Judge for the MCP agent loop. Runs a single extraction pass with
the given parameters and returns a structured report indicating whether the
result is clean or needs adjustment. The MCP test_parameters tool calls
this in a loop until status == "success".
test_extraction(
file,
page,
area = NULL,
method = c("bbox", "lattice", "stream", "llm"),
header_rows = 1L,
label = "target",
provider = "anthropic",
schema = NULL,
preview_rows = 3L,
...
)
file |
Path to a PDF file. |
page |
Page number (integer). |
area |
Named |
method |
Extraction method: |
header_rows |
Number of header rows (default 1). |
label |
Internal table label used during extraction (default
|
provider |
LLM provider, only used when |
schema |
Named character vector of column types, only used when
|
preview_rows |
Number of data rows to include in the response preview (default 3). Keeps the agent context window small. |
... |
Additional arguments forwarded to the extraction function. |
Returns a list that serialises cleanly to JSON via jsonlite::toJSON().
A list with:
status"success", "needs_alignment", "empty", or
"crash".
metricsStructural quality metrics: row/col counts, unnamed headers, empty columns, header-spill detection, likely-numeric character columns.
guidancePlain-English action string for the agent when status
is not "success".
previewFirst preview_rows rows as a list of named lists for
JSON serialisation.
Replays a macro (or accepts a pre-replayed table list) and compares the
output against a stored YAML snapshot. On the first call the snapshot is
written; subsequent calls compare against it. Designed for use inside
testthat::test_that() blocks but also works standalone.
test_macro(
file = NULL,
macro = NULL,
tables = NULL,
macro_path = ".",
params = list(),
snapshot_dir = file.path("tests", "testthat", "macro-snapshots"),
name = NULL,
update = identical(Sys.getenv("TESTTHAT_SNAPSHOT_UPDATE"), "true"),
n_head = 5L
)
file |
Path to the PDF file. Ignored when |
macro |
Macro name, path, or step list. Ignored when |
tables |
A pre-replayed named list of data frames (the result of
|
macro_path |
Directory for macro lookup (default |
params |
Named list of macro parameter values passed to |
snapshot_dir |
Directory in which to read/write snapshot files (default
|
name |
Snapshot file stem. Defaults to the macro name when |
update |
If |
n_head |
Number of header rows captured in the snapshot for spot-checking (default 5). |
Workflow:
Call test_macro(file, macro = "my_macro") locally with the reference PDF.
The snapshot is written to snapshot_dir.
Commit the snapshot file alongside your package.
In CI, either replay with the same PDF or supply tables directly.
test_macro() compares against the committed snapshot and fails on drift.
The replayed table list, invisibly.
Update the prompt for a recorded select_item step and re-extract
update_item(
sess,
label,
prompt = NULL,
cast = NULL,
chat = NULL,
re_extract = TRUE
)
sess |
A |
label |
Label of the item to update. |
prompt |
New prompt string. |
cast |
New cast type, or |
chat |
An existing |
re_extract |
Re-run the LLM call immediately (default |
sess invisibly.
Finds the most recent select_table_llm step for label, replaces its
schema, and re-runs the extraction against the same page/area. Useful
when the auto-detected columns need renaming or the types need adjustment.
update_llm_schema(
sess,
label,
schema,
prompt = NULL,
chat = NULL,
re_extract = TRUE
)
sess |
A |
label |
Label of the table to update. |
schema |
New named character vector: |
prompt |
Replacement prompt, or |
chat |
An existing |
re_extract |
Re-run the LLM call immediately (default |
sess invisibly.
Runs a pre-flight check on every step. Agents should call this after
generating a macro and fix any errors before the human runs mx_replay().
validate_macro(file, macro)
file |
Path to a PDF file. |
macro |
Either a step list or a path to a |
A macrox_validation list with $valid, $steps (data frame),
and $errors (character vector).
Uses the validate package DSL. Rules are named character strings
containing R expressions evaluated against the data frame. Both row-level
predicates (total_count > 0) and table-level aggregates (nrow(.) == 12)
are supported.
validate_table(sess, table, rules, strict = FALSE)
sess |
A |
table |
Character label of the table to validate. |
rules |
Named character vector or named list of R expression strings.
Names become the rule identifiers shown in reports. Alternatively, a
|
strict |
If |
Results are stored in sess$validations[[table]] for later inspection.
On replay, failures produce warnings by default; set strict = TRUE to
abort.
sess invisibly (step is recorded).
sess |> validate_table("calf_monthly", rules = c(
no_na_month = "!anyNA(month)",
positive_males = "all(male_count > 0, na.rm = TRUE)",
twelve_rows = "nrow(.) == 12"
))
Renders the PDF page for a select_table or select_table_llm step and
opens it in the RStudio Viewer or system browser. If the step used a
bounding box, the selected area is highlighted in blue. Requires magick
for annotations (Suggests).
view_in_pdf(sess, step = NULL, dpi = 150)
sess |
A |
step |
Integer step index. Defaults to the most recent step with a
page location ( |
dpi |
Render resolution (default 150). |
The bounding box area (named numeric vector or NULL), invisibly.