Skip to content

The Ten Axes

An experiment is a grid. Each row below is one axis of that grid — one decision you can hold still or sweep. They are exactly the ten keys under grid: in a config file, and the ten keyword arguments of Lab().grid(...) in Python.

Nine of the ten pick a plugin by name (a spec string like "recursive:512" — see Chunkers for the grammar). The tenth, candidates, is a plain integer.

AxisWhat it isOptions that shipNeed an extra
ingestionWhat goes into the index, and what a hit on it returns8none
parserReads a source file into text86 of 8
chunkerCuts a parsed document into retrievable pieces127 of 12
embedderTurns text into vectors51 of 5
indexHow the search itself is done73 of 7
transformRewrites the question before searching with it6none, but 4 of 6 need run.model set
retrievalHow the index is used, as opposed to what it is5none
rerankerReorders what came back51 of 5
candidatesHow deep the reranker gets to look before it reordersnot a plugin — an integern/a
generatorTurns retrieved passages into an answer, or stops at retrieval2none, but the llm one needs run.model set

Reading the “need an extra” column

A plugin that needs an extra is still registered and still shows up in PARSERS.names() or cg.CHUNKERS.names() — installing nothing does not shrink the list of names, it just makes some of them fail when you actually build or run them. Building cg.get_parser("marker") never fails; calling .parse(...) on the result does, with a message naming the exact pip extra to install. The same shape holds for every other axis: constructing the plugin succeeds, using it is what raises MissingExtraError.

Two axes are a partial exception. transform and generator both have plugins that need no extra at all but still will not run until you set run.model in your config (or pass an llm in Python) — a missing API key or unset model is a different failure than a missing package, and the axis pages for Transforms and Generation say which plugins need which.

Defaults

Leave an axis out of grid: entirely and it runs at a single default value rather than being swept:

AxisDefault
ingestionplain
parsermarkdown
chunkerrecursive:512
embeddertfidf
indexdense
transformnone (no rewriting)
retrievalsimple
rerankernone (keeps retriever order)
candidates50
generatornone (the sweep stops at retrieval)