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 --frozenThe 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.
| Path | Contents |
|---|---|
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:
| Path | Contents |
|---|---|
pricing.py | Helpers 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.py | Candidate 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.py | Refusals, 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.py | Implement the backend interface and report supported configurations. |
lowering.py | Lower one candidate and bind its runtime prompts. |
executor/runtime.py | Bind loaded model and query state, then dispatch execution. |
executor/model_loading.py | Resolve model files and load weights. |
executor/admission.py | Admit 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 -qAll 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 devOpen the local site. Check the changed pages, then run:
pnpm --dir docs types:check
pnpm --dir docs buildSubmit 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.