PaperLab.space
Docs / Python API reference
Reference

Python API reference

Every public class and function, grouped by task.

Most names import from the top-level package: from paperlab_space import run. Each entry shows its import path.

Running

Run an evaluation and estimate its cost.

run

Python
from paperlab_space import run

def run(
    config: RunConfig,
    data: Dataset | MappedDataset | None = None,
    *,
    backend: Backend | None = None,
    on_progress: ProgressCallback | None = None,
    previous: RunResults | None = None,
    checkpoint: str | Path | None = None,
) -> RunResults

Run an evaluation and return outputs and scores.

Works in scripts and in Jupyter (where an event loop is already running). See arun for the arguments.

arun

Python
from paperlab_space import arun

async def arun(
    config: RunConfig,
    data: Dataset | MappedDataset | None = None,
    *,
    backend: Backend | None = None,
    on_progress: ProgressCallback | None = None,
    previous: RunResults | None = None,
    checkpoint: str | Path | None = None,
    sleep: Sleep = asyncio.sleep,
    clock: Clock = time.monotonic,
) -> RunResults

Run an evaluation asynchronously.

Arguments

  • config: What to run.
  • data: The data. If omitted, it is loaded from config.dataset. A plain Dataset is mapped with config.mapping.
  • backend: Where to send requests. Defaults to LiteLLMBackend.
  • on_progress: Called after each row finishes.
  • previous: Results of an earlier, interrupted run with the same config. Rows that already have an output are reused instead of requested again.
  • checkpoint: A results.json path to save finished rows to while the run goes, and when it stops early (Ctrl+C, an error). Pass the file as previous to continue. When the run finishes, the full results are written there.
  • sleep, clock: Injection points for tests.

estimate

Python
from paperlab_space import estimate

def estimate(
    config: RunConfig,
    data: Dataset | MappedDataset,
    *,
    backend: Backend | None = None,
    latency_s: float = 3.0,
) -> Estimate

Estimate tokens, cost, and wall time for each model.

Token counts use a script-aware heuristic, not the model's tokenizer, so treat them as ballpark figures. latency_s is the assumed time per request.

Estimate

Python
from paperlab_space.runner import Estimate

Estimate(models: list[ModelEstimate])
AttributeTypeDefaultDescription
modelslist[ModelEstimate]required

Properties

  • cost_usd (float | None)
  • minutes (float): Models run in parallel, so the slowest one sets the total.

Progress

Python
from paperlab_space import Progress

Progress(
    model: str,
    done: int,
    failed: int,
    total: int,
    record_id: str,
    row: RowOutput | None = None,
)

A progress update, sent after each row finishes.

AttributeTypeDefaultDescription
modelstrrequiredThe model's label.
doneintrequiredRows finished for this model, successful or not.
failedintrequiredRows that failed so far for this model.
totalintrequiredRows to run for this model.
record_idstrrequiredThe row that just finished.
rowRowOutput | NoneNoneIts output, so callers can checkpoint partial results (see previous in arun).

LiteLLMBackend

Python
from paperlab_space import LiteLLMBackend

LiteLLMBackend(
    api_keys: Mapping[str, str] | None = None,
    api_bases: Mapping[str, str] | None = None,
)

Calls models through LiteLLM.

API keys are read from the usual environment variables (OPENROUTER_API_KEY, GEMINI_API_KEY, OPENAI_API_KEY, ...) unless passed in api_keys, keyed by provider prefix (e.g. {"openrouter": "sk-or-..."}). Keys are never stored in the run config or results.

complete

Python
async def complete(
    model: ModelSpec,
    messages: Messages,
    *,
    seed: int | None,
    timeout: float,
) -> Completion

price

Python
def price(model: ModelSpec) -> tuple[float, float] | None

Configuration

The run config and its parts. See the config file reference for the YAML form.

RunConfig

Python
from paperlab_space import RunConfig

Everything needed to run (and re-run) an evaluation.

AttributeTypeDefaultDescription
datasetDatasetSpec | NoneNoneWhere to load the data from. Optional when the data is passed to run directly.
mappingColumnMappingrequiredWhich columns are inputs, context, the answer key, and the row ID.
promptPromptTemplaterequiredThe prompt template: a string, or an object with user and system.
modelslist[ModelSpec]requiredModels to evaluate, as IDs or objects with options.
metricslist[MetricSpec][]Metrics to compute, as names or objects with options. Empty collects outputs only.
seedint | NoneNoneDefault seed for models that do not set their own.
concurrencyint4Parallel requests per model (rate limits still apply).
retryRetrySettingsRetrySettings()Retry and timeout settings.

model_seed

Python
def model_seed(model: ModelSpec) -> int | None

from_dict (classmethod)

Python
def from_dict(data: dict[str, Any]) -> RunConfig

Build from a dict; also accepts a reproducibility file (config under config).

from_yaml (classmethod)

Python
def from_yaml(path: str | Path) -> RunConfig

Load a YAML config. A relative dataset path is resolved against the file's folder.

to_dict

Python
def to_dict() -> dict[str, Any]

to_yaml

Python
def to_yaml(path: str | Path | None = None) -> str

ModelSpec

Python
from paperlab_space import ModelSpec

A model to evaluate, addressed by its LiteLLM ID (provider/model).

AttributeTypeDefaultDescription
idstrrequiredLiteLLM model ID with its provider prefix, e.g. gemini/gemini-3.5-flash.
labelstr | NoneNoneDisplay name in tables. Defaults to the model ID without the provider prefix.
temperaturefloat0.0Sampling temperature. 0 gives the most repeatable outputs.
max_tokensint | NoneNoneCap on output tokens per response.
top_pfloat | NoneNoneNucleus sampling cutoff.
seedint | NoneNoneOverrides the run-level seed for this model.
requests_per_minutefloat | NoneNoneOverride the default rate limit for this model.
concurrencyint | NoneNoneOverride the run-level number of parallel requests for this model.
paramsdict[str, Any]{}Extra provider parameters passed through to LiteLLM.

Properties

  • provider (str)
  • name (str): The label used in outputs.

MetricSpec

Python
from paperlab_space import MetricSpec

A metric name plus its options, e.g. {"name": "exact_match", "ignore_case": false}.

AttributeTypeDefaultDescription
namestrrequiredA registered metric name; paperlab-space metrics lists them.
labelstr | NoneNoneColumn name in outputs; needed to use the same metric twice with different options.
paramsdict[str, Any]{}Metric options such as labels or ignore_case. In YAML they can also sit next to name.

Properties

  • key (str)

DatasetSpec

Python
from paperlab_space import DatasetSpec

Where the data comes from. Optional when the dataset is passed in directly.

AttributeTypeDefaultDescription
pathstrrequiredData file. A relative path is resolved against the config file's folder.
sheetstr | int | NoneNoneExcel sheet name or zero-based index. Defaults to the first sheet.

RetrySettings

Python
from paperlab_space import RetrySettings

How failed requests are retried, and how long to wait for a response.

AttributeTypeDefaultDescription
max_attemptsint5Tries per row, including the first.
base_delayfloat2.0Seconds before the first retry; doubles on each attempt.
max_delayfloat60.0Upper bound on the wait between retries, in seconds.
timeoutfloat120.0Seconds to wait for one model response.

ColumnMapping

Python
from paperlab_space import ColumnMapping

Which columns are inputs, extra context, the expected answer, and the row ID.

Input and context columns become variables in the prompt template. The expected column is never exposed to the prompt, so answers cannot leak into it.

AttributeTypeDefaultDescription
inputlist[str]requiredColumns available to the prompt template. One name or a list.
contextlist[str][]More columns available to the prompt, such as metadata.
expectedstr | NoneNoneThe answer key that outputs are scored against. Never available to the prompt.
idstr | NoneNoneA stable row ID. Defaults to the 1-based row number.
answer_delimiterstr | NoneNoneSplit the expected cell on this string to allow several valid answers, e.g. "|".

Properties

  • fields (list[str]): Columns available to the prompt template.
  • used_columns (list[str])

PromptTemplate

Python
from paperlab_space import PromptTemplate

PromptTemplate(user: str | None = None, /, **data: Any)

A user prompt (and optional system prompt) with column placeholders.

Python
>>> PromptTemplate(user="Translate to English: {sentence}").render({"sentence": "สวัสดี"})
[{'role': 'user', 'content': 'Translate to English: สวัสดี'}]
AttributeTypeDefaultDescription
userstrrequiredThe user message, with {column} placeholders.
systemstr | NoneNoneAn optional system message, with the same placeholders.

Properties

  • variables (list[str]): Placeholder names in order of first appearance (user prompt, then system).

check

Python
def check(columns: Iterable[str]) -> None

Raise TemplateError if a placeholder is not one of columns.

render

Python
def render(fields: Mapping[str, str | None]) -> list[dict[str, str]]

Fill the template and return chat messages. Empty cells become empty strings.

Data

Load, map, and validate spreadsheet data.

load_dataset

Python
from paperlab_space import load_dataset

def load_dataset(path: str | Path, sheet: str | int | None = None) -> Dataset

Load an .xlsx or .csv/.tsv file.

The first non-empty row is used as the header. Fully empty rows are dropped.

Arguments

  • path: File to load.
  • sheet: Excel sheet name or zero-based index. Defaults to the first sheet. Ignored for CSV files.

list_sheets

Python
from paperlab_space import list_sheets

def list_sheets(path: str | Path) -> list[str]

Return the sheet names of an Excel file (a CSV file has a single unnamed sheet).

Dataset

Python
from paperlab_space import Dataset

Dataset(
    columns: list[str],
    rows: list[Row],
    source: str | None = None,
    sheet: str | None = None,
    sha256: str | None = None,
    encoding: str | None = None,
    warnings: list[str] = [],
)

A rectangular table of string cells with named columns.

AttributeTypeDefaultDescription
columnslist[str]required
rowslist[Row]required
sourcestr | NoneNone
sheetstr | NoneNone
sha256str | NoneNone
encodingstr | NoneNone
warningslist[str][]

column

Python
def column(name: str) -> list[str | None]

Return all values of one column.

map

Python
def map(mapping: ColumnMapping) -> MappedDataset

Apply a column mapping, producing records ready for prompting and scoring.

from_records (classmethod)

Python
def from_records(
    records: Sequence[dict[str, Any]],
    source: str | None = None,
) -> Dataset

Build a dataset from a list of dicts (column order follows first appearance).

MappedDataset

Python
from paperlab_space import MappedDataset

MappedDataset(
    records: list[Record],
    mapping: ColumnMapping,
    dataset: Dataset,
)

A dataset with a column mapping applied, ready for prompting and scoring.

AttributeTypeDefaultDescription
recordslist[Record]required
mappingColumnMappingrequired
datasetDatasetrequiredThe unmapped data.

Properties

  • has_answer_key (bool)

from_dataset (classmethod)

Python
def from_dataset(dataset: Dataset, mapping: ColumnMapping) -> MappedDataset

validate

Python
def validate() -> ValidationReport

Check the data for empty cells, duplicate IDs, and encoding problems.

preview

Python
def preview(n: int = 5) -> list[dict[str, Any]]

The first n records as JSON-ready dicts.

to_jsonl

Python
def to_jsonl(path: str | Path | None = None) -> str

Serialise all records as JSON Lines (UTF-8, non-ASCII kept as-is).

Record

Python
from paperlab_space.data import Record

Record(
    id: str,
    fields: dict[str, str | None],
    expected: list[str] | None,
    row_number: int,
)

One evaluation example.

AttributeTypeDefaultDescription
idstrrequiredThe row ID, or the row number if the mapping has no ID column.
fieldsdict[str, str | None]requiredInput and context values by column name.
expectedlist[str] | NonerequiredValid answers, or None without an answer key entry.
row_numberintrequired1-based position among the data rows (header excluded).

to_json

Python
def to_json() -> dict[str, Any]

ValidationReport

Python
from paperlab_space.data import ValidationReport

ValidationReport(issues: list[Issue], n_records: int)

The result of validating mapped data.

AttributeTypeDefaultDescription
issueslist[Issue]required
n_recordsintrequired

Properties

  • ok (bool): True if there are no errors (warnings are allowed).
  • errors (list[Issue])
  • warnings (list[Issue])

Issue

Python
from paperlab_space.data import Issue

Issue(
    level: Level,
    code: str,
    message: str,
    rows: list[int] = [],
    column: str | None = None,
)

One problem found in the data.

AttributeTypeDefaultDescription
levelLevelrequired"error" blocks a run; "warning" does not.
codestrrequiredA stable identifier, e.g. empty_input or duplicate_id.
messagestrrequired
rowslist[int][]1-based data row numbers (header excluded).
columnstr | NoneNoneThe column the problem is in, if any.

Results

What a run returns.

RunResults

Python
from paperlab_space import RunResults

RunResults(
    config: RunConfig,
    data: MappedDataset,
    runs: dict[str, ModelRun],
    scores: dict[str, dict[str, MetricResult]] = {},
    started_at: str | None = None,
    finished_at: str | None = None,
    environment: dict[str, str] = ...,
)

Everything a run produced: outputs, scores, and the config and data behind them.

AttributeTypeDefaultDescription
configRunConfigrequired
dataMappedDatasetrequiredThe data the run used, with the mapping applied.
runsdict[str, ModelRun]requiredModel name -> outputs, in config order.
scoresdict[str, dict[str, MetricResult]]{}Model name -> metric name -> result.
started_atstr | NoneNoneISO 8601 timestamp (UTC).
finished_atstr | NoneNoneISO 8601 timestamp (UTC).
environmentdict[str, str]...Python, paperlab-space, and LiteLLM versions.

Properties

  • model_names (list[str])

output

Python
def output(model: str, record_id: str) -> RowOutput

to_dict

Python
def to_dict() -> dict[str, Any]

save_json

Python
def save_json(path: str | Path) -> None

from_dict (classmethod)

Python
def from_dict(data: dict[str, Any]) -> RunResults

load_json (classmethod)

Python
def load_json(path: str | Path) -> RunResults

ModelRun

Python
from paperlab_space import ModelRun

ModelRun(model: ModelSpec, rows: list[RowOutput])

One model's outputs for every row.

AttributeTypeDefaultDescription
modelModelSpecrequired
rowslist[RowOutput]requiredOne output per data row, in data order.

Properties

  • name (str)
  • n_failed (int)
  • cost_usd (float | None)
  • input_tokens (int)
  • output_tokens (int)
  • model_versions (list[str])

RowOutput

Python
from paperlab_space import RowOutput

RowOutput(
    record_id: str,
    output: str | None,
    error: str | None = None,
    attempts: int = 0,
    latency_s: float | None = None,
    input_tokens: int | None = None,
    output_tokens: int | None = None,
    cost_usd: float | None = None,
    model_version: str | None = None,
)
AttributeTypeDefaultDescription
record_idstrrequiredThe ID of the data row.
outputstr | NonerequiredThe model's answer, or None if every attempt failed.
errorstr | NoneNoneWhy the request failed, if it did.
attemptsint0Requests sent for this row, including retries.
latency_sfloat | NoneNoneSeconds the successful request took.
input_tokensint | NoneNone
output_tokensint | NoneNone
cost_usdfloat | NoneNoneCost in USD, if the provider's price is known.
model_versionstr | NoneNoneThe exact model name the provider reported.

Properties

  • ok (bool)

MetricResult

Python
from paperlab_space import MetricResult

MetricResult(
    name: str,
    value: float | None,
    per_row: list[float | None] | None = None,
    extra: dict[str, float] = {},
    n_scored: int = 0,
    higher_is_better: bool = True,
)

The score of one metric for one model.

AttributeTypeDefaultDescription
namestrrequiredThe metric's key: its label, or its name.
valuefloat | NonerequiredThe headline number (None if no row could be scored).
per_rowlist[float | None] | NoneNoneRow-level scores aligned with the dataset records, if the metric has them.
extradict[str, float]{}Secondary numbers, e.g. precision and recall next to F1.
n_scoredint0Rows that counted towards the score.
higher_is_betterboolTrue

Metrics

Score results and add your own metrics. See Custom metrics.

score

Python
from paperlab_space import score

def score(results: RunResults) -> dict[str, dict[str, MetricResult]]

Compute every configured metric for every model in results.

available_metrics

Python
from paperlab_space import available_metrics

def available_metrics() -> dict[str, type[Metric]]

register

Python
from paperlab_space import register

def register(cls: type[Metric]) -> type[Metric]

Class decorator that makes a metric available by name in run configs.

Metric

Python
from paperlab_space.metrics import Metric

Base class for metrics. Subclasses declare their options as __init__ arguments.

AttributeTypeDefaultDescription
namestrrequiredThe name used in run configs.
descriptionstr''One sentence, shown by paperlab-space metrics.
requires_referenceboolTrueWhether the metric needs an expected-answer column.
higher_is_betterboolTrueWhich way is better, so the LaTeX table bolds the right score.

compute

Python
def compute(predictions: Predictions, references: References) -> MetricResult

Score all rows of one model.

result

Python
def result(value: float | None, **kwargs: Any) -> MetricResult

Normalizer

Python
from paperlab_space.metrics import Normalizer

Normalizer(
    nfkc: bool = True,
    ignore_case: bool = True,
    trim_punctuation: bool = True,
    ignore_punctuation: bool = False,
    remove_articles: bool = False,
)

How to normalise text before comparing a prediction to a reference.

Defaults suit short answers and labels: NFKC (so full-width ABC equals ABC), case-insensitive, whitespace collapsed, and quotes/punctuation trimmed from the ends (so "Positive." matches positive).

AttributeTypeDefaultDescription
nfkcboolTrueApply Unicode NFKC, so full-width characters equal their ASCII forms.
ignore_caseboolTrueCompare case-insensitively.
trim_punctuationboolTrueStrip punctuation and quotes from the start and end only.
ignore_punctuationboolFalseRemove all punctuation, including inside the text.
remove_articlesboolFalseRemove English articles (a, an, the), as in SQuAD-style evaluation.

tokenize

Python
from paperlab_space.metrics import tokenize

def tokenize(text: str) -> list[str]

Split on whitespace, and into single characters for scripts written without spaces between words (Chinese, Japanese, Thai, Lao, Khmer, Burmese, Tibetan).

Korean uses spaces between words, so Hangul is split on whitespace like Latin text.

extract_label

Python
from paperlab_space.metrics import extract_label

def extract_label(text: str, labels: Sequence[str], normalize: Normalizer) -> str

Map a free-form answer to one of labels.

Returns the matching label if the normalised answer equals one, or if exactly one label appears in it ("The sentiment is positive." -> positive). Otherwise the normalised answer is returned unchanged and will not match any label.

Export

Write results to files. from paperlab_space import export.

write_all

Python
from paperlab_space.export import write_all

def write_all(results: RunResults, out_dir: str | Path) -> dict[str, Path]

Write every export format into out_dir and return the paths by format.

write_excel

Python
from paperlab_space.export import write_excel

def write_excel(results: RunResults, path: str | Path) -> Path

Write results to an .xlsx workbook with Summary, Outputs, and Config sheets.

write_latex

Python
from paperlab_space.export import write_latex

def write_latex(results: RunResults, path: str | Path, **options: Any) -> Path

Write latex_table output to path. Options are passed through.

latex_table

Python
from paperlab_space.export import latex_table

def latex_table(
    results: RunResults,
    *,
    metrics: Sequence[str] | None = None,
    caption: str | None = None,
    label: str | None = 'tab:results',
    decimals: int = 1,
    percent: bool = True,
    bold_best: bool = True,
    floating: bool = True,
) -> str

Build a model-by-metric comparison table.

Arguments

  • metrics: Metric keys to include, in order. Defaults to all configured metrics.
  • percent: Show scores in [0, 1] as percentages.
  • bold_best: Bold the best score in each column (all of them on ties).
  • floating: Wrap the tabular in a table environment with caption and label.

write_repro

Python
from paperlab_space.export import write_repro

def write_repro(results: RunResults, path: str | Path) -> Path

reproducibility

Python
from paperlab_space.export import reproducibility

def reproducibility(results: RunResults) -> dict[str, Any]

Backends

Send requests somewhere other than LiteLLM. See Custom backends.

Backend

Python
from paperlab_space.runner import Backend

A protocol: any class with these methods works.

complete

Python
async def complete(
    model: ModelSpec,
    messages: Messages,
    *,
    seed: int | None,
    timeout: float,
) -> Completion

Return one completion, raising RetryableError or ProviderError.

price

Python
def price(model: ModelSpec) -> tuple[float, float] | None

USD per input token and per output token, or None if unknown.

Completion

Python
from paperlab_space.runner import Completion

Completion(
    text: str,
    input_tokens: int | None = None,
    output_tokens: int | None = None,
    cost_usd: float | None = None,
    model_version: str | None = None,
)

One model response, as a backend returns it.

AttributeTypeDefaultDescription
textstrrequiredThe model's answer.
input_tokensint | NoneNonePrompt tokens, as reported by the provider.
output_tokensint | NoneNoneOutput tokens, as reported by the provider.
cost_usdfloat | NoneNoneCost in USD, if known.
model_versionstr | NoneNoneThe exact model name reported by the provider, if any.

RetryableError

Python
from paperlab_space.runner import RetryableError

RetryableError(message: str, retry_after: float | None = None)

A transient failure (rate limit, timeout, server error) worth retrying.

Subclass of PaperLabError.

ProviderError

Python
from paperlab_space.runner import ProviderError

ProviderError(message: str, fatal: bool = False)

A permanent failure for one request.

If fatal is true the problem affects every request to this model (bad API key, unknown model), so the runner stops sending requests to it.

Subclass of PaperLabError.

Errors

Every error the package raises on purpose is a PaperLabError.

PaperLabError

Python
from paperlab_space import PaperLabError

Base class for all paperlab-space errors.

Subclass of Exception.

ConfigError

Python
from paperlab_space import ConfigError

A run configuration is invalid.

Subclass of PaperLabError.

DataError

Python
from paperlab_space import DataError

The input data or column mapping is invalid.

Subclass of PaperLabError.

TemplateError

Python
from paperlab_space import TemplateError

A prompt template is invalid or references unknown columns.

Subclass of PaperLabError.