Quail
Contributing

Overview

Here we explain how to report a bug or submit a change to Quail.

Report a bug

If you find a bug, please open an issue. Include:

  • A minimal example that reproduces the bug.
  • The expected behavior and what happened.
  • The Quail version or commit. For an inference error, include the model, device, and backend configuration.

Prepare the repository

Quail requires Python 3.12. Clone the repository and install the development dependencies:

git clone https://github.com/fsdatalab/quail.git
cd quail
uv sync --frozen

The development dependencies include quail-b. You need access to that repository to install them.

Make a change

For a new feature or a substantial change, open an issue to discuss the approach before implementation. Include the tests and documentation needed to check and use your change.

PathContents
quail/api/Session, Query, and running a query in this process.
quail/frontend/SQL parsing.
quail/catalog/Table providers and the tokenized inputs of a session.
quail/logical/, quail/physical/Logical and physical plan definitions.
quail/planner/, quail/cost/, quail/specs/Planning rules, cost estimates, and model and device specifications.
quail/execution/The runner and the CPU operators.
quail/backends/The Quail inference engine.
quail/baselines/The stock vLLM and SGLang backends the benchmark compares against.
quail/remote/, quail/server/The client and server of Quail Server.
quail/deploy/The Modal images.
bench/The QUAIL-B runner, outside the wheel.
tests/, experiments/CPU tests and Modal GPU scripts.
docs/, demos/Documentation and examples.

Each package imports only the packages below it in the list in pyproject.toml under [tool.importlinter]; uv run lint-imports checks that.

quail/planner/ has one subpackage per planning stage. The table runs from top to bottom, and lint-imports holds the planner to this order too:

PathContents
pricing.pyHelpers that price a logical plan through the same search as the query planner.
rules/logical.py changes query trees. physical.py changes executable graphs.
graph/GraphBuilder, which turns the planner's decisions into a physical graph, plus shards, retention, and result operators.
sol/The speed-of-light estimate and its plan search.
search/operator_order.py assembles the chosen filter order, join order, and anchors. filter_order.py and join_order.py implement the searches.
operators/One module per AI operator (filter, join, score, classify, extract) with its statistics, cost, spec, and emit_* functions that add its plan nodes.
statistics/Table length summaries and pool_split, the KV pool split every operator reads.
optimize.pyCandidate generation, refinement, and final selection.
optimizer/context.py holds planning inputs. candidates.py defines candidate plans and the backend planner interface. tree_rewrites.py and graph_refinement.py apply the two rule interfaces in rules.py.
validation.py, prompt_lowering.py, plan.pyRefusals, prompt tokenization, and PhysicalPlan.

To add an AI operator, add a module under operators/ and call its emit_* function from GraphBuilder in graph/builder.py.

For module names, follow the Google Python naming guidance. Use descriptive snake_case names and avoid unfamiliar abbreviations. Keep related classes and functions together. Choose the name from the module's responsibility, such as model_loading.py or admission.py.

The Quail backend separates its entry point from lowering and execution:

Path under quail/backends/quail/Responsibility
backend.pyImplement the backend interface and report supported configurations.
lowering.pyLower one candidate and bind its runtime prompts.
executor/runtime.pyBind loaded model and query state, then dispatch execution.
executor/model_loading.pyResolve model files and load weights.
executor/admission.pyAdmit requests within token and KV budgets.

See Architecture for the query execution flow. See Extending Quail for the extension interfaces.

Check the change

Code checks

Run these commands from the repository root:

uv run ruff check quail bench tests experiments tools
uv run python tools/check_long_strings.py
uv run vulture
uv run lint-imports
uv run pytest -q

All four checks must pass before pushing. These checks do not require a GPU.

For changes to model execution, run the relevant GPU tests. The script experiments/run_gpu_tests.py runs these tests on Modal. For performance changes, use the benchmark guide.

Documentation checks

Install the documentation dependencies and start the site:

pnpm --dir docs install --frozen-lockfile
pnpm --dir docs dev

Open the local site. Check the changed pages, then run:

pnpm --dir docs types:check
pnpm --dir docs build

Submit a pull request

Describe the problem, what your change does, and why. List the checks you ran and their results. For a performance change, include the configurations, measurements, and saved result paths. State any remaining limitations.

On this page