Repository navigation
Checkpoints and Dedupe
out = job.run(
df,
backend="spark", # or "local" / "multiprocessing"
checkpoint="/Volumes/main/ml/checkpoints/ticket_routing",
id_col="ticket_id",
)Results are persisted while the run progresses. When a run is interrupted (cluster restart, spot loss, Ctrl-C, quota exhausted), the same call continues where it stopped. Rows already stored are not sent to the model again.
-
id_colmust hold unique strings or integers. This is checked first: missing ids, other types and duplicates are aConfigError. - A checkpoint directory belongs to one job. Its manifest stores the job's
fingerprint(), which covers everything that changes results: model identity, task, prompt/system/text/audio settings, output schema, sampling, engine. A different job on the same directory is aConfigError. Use a new directory when you change the prompt. Options that don't change results (engine_options,copy_to_local,stage_dir,api_key_env) can change between runs. - Rows stored with an error are processed again on the next run (
retry_failed=True, default). Withretry_failed=Falsethey are returned as stored. - Per id, a stored success wins over a stored failure, then the newest result.
- The input may grow between runs: only new and failed ids are processed.
Directory layout: manifest.json + results/part-*.jsonl (one JSON object per row: id,
value, error, meta). Finished batches are buffered and flushed every
checkpoint_every rows (default 1 000), at the end, and on interrupts. A hard kill
loses at most one buffer.
With a checkpoint, the Spark run is eager:
- Check
id_coluniqueness (one aggregation). - Skip ids already stored (anti-join).
- Process the rest in waves of
checkpoint_everyrows (default 10 000). Each wave is one Spark job whose results are appended to<checkpoint>/results(parquet, typed output columns +_written_at). - Return the input left-joined with the stored results.
The returned DataFrame only reads parquet: further actions don't run inference again. A failure loses at most the wave in progress. Smaller waves mean finer-grained progress, at a few seconds of Spark overhead per wave.
The checkpoint path is any path Spark can read and write: /Volumes/..., dbfs:/...,
s3://..., abfss://..., or a local path on single-node clusters.
# Spark
spark.read.parquet("/Volumes/main/ml/checkpoints/ticket_routing/results").groupBy(
F.col("output_error").isNull()
).count().show()
# local
import pandas as pd, glob
pd.concat(pd.read_json(f, lines=True) for f in glob.glob("ckpt/results/*.jsonl"))job.run(df, dedupe=True)Rows with identical values in the job's input columns (the template's columns, or the
audio column) are sent to the model once. The other rows get the same value or error.
Their meta has attempts=0 and no tokens or latency, so statistics and costs count the
call once and RunStats.reused reports how many rows were served this way.
-
local/multiprocessing: across the whole input (of the rows still to process, with a checkpoint). -
spark: within each Arrow batch (no extra shuffle). For global dedupe on Spark, run the job ondf.select(cols).distinct()and join the results back.
Dedupe is only safe when identical inputs should produce identical outputs, which is
true for temperature=0, embeddings and transcription. With sampling you trade
diversity for cost.
distribatch · Apache-2.0 · repository · issues
Getting started
Jobs
Running
Results
Guides