Skip to main content

Cell types and models

A QRY notebook is a sequence of cells, and each cell can be one of three types and use its own model. Knowing which combination to pick is the difference between a notebook that takes 2 seconds and 5 cents to run, and one that takes 2 minutes and 50 cents.

The three cell types

SQL

Runs against the notebook's bound datasource. The cell shows the SQL query and (after running) a results table with sort, pagination, and CSV export.

SELECT category, SUM(revenue) AS total
FROM orders
WHERE order_date >= '{{this_month_start}}'
GROUP BY category
ORDER BY total DESC;

Date variables ({{today}}, {{this_month_start}}, …) resolve at execution time — handy when the notebook is scheduled. They're literal strings outside of execution, so editing the SQL with the variable in place won't preview-substitute.

Python

Runs in QRY's Python execution environment. Each cell is independent unless you explicitly persist data in df_cache or similar shared state — there's no notebook-wide kernel.

import pandas as pd

df = qry.sql("SELECT * FROM customers WHERE balance > 10000")
df.groupby('country')['balance'].agg(['count', 'mean', 'sum'])

The qry object exposes:

  • qry.sql("...") — run a SQL query against the bound datasource and return a DataFrame.
  • qry.cell(<id>) — reference output of a previous cell by id.
  • Any standard library + the heavy libraries QRY detects (pandas, numpy, matplotlib, plotly, scikit-learn, xgboost, lightgbm, statsmodels, ...).

See Running Python for the executor routing (Gemini-native vs. Kubernetes) and resource limits.

Markdown

Documentation between code cells — section headers, narrative, links, images. Doesn't execute, just renders.

Useful for notebooks shared with the team: a Markdown cell at the top explaining the goal, plus headings before each section, makes the notebook readable.

Per-cell model selection

Each cell has its own model picker (top-right of the cell). Three patterns work well in practice:

Cheap default, strong finale

For most notebooks, use a fast / cheap model (Haiku, Gemini Flash) for the routine cells (SQL generation, simple Python) and a strong model (Sonnet, Gemini Pro) for the final synthesis cell that builds the report or chart.

This keeps the per-run cost low without sacrificing the part that actually matters.

Same model throughout

For deterministic notebooks (scheduled runs, regulated reporting) use one model end-to-end. Switching between providers can produce subtle output drift across runs even on identical inputs.

Strong-only for one tricky cell

If most of the notebook is fine on the cheap model but one cell needs careful reasoning (e.g. "summarise these 200 customer notes into 5 themes"), set the strong model on that cell only.

What's shared across cells

Notebook-wide:

  • Datasource binding (and its catalog / schema scope).
  • Schedule (if scheduled).
  • Domain context (tenant + workspace + personal).

Per-cell:

  • Model.
  • Cell type.
  • Output.

Common issues

A SQL cell can't see a table I expect. Check the notebook's datasource. Cells query the notebook-bound datasource, not whatever your last conversation was using.

A Python cell errors with qry not defined. The qry object is injected only inside Python cells in QRY notebooks. Outside notebooks (e.g. running the same code locally), it doesn't exist.

Per-cell output disappears after re-run. Re-running a cell replaces its output. To compare versions, copy the output (or its CSV export) before re-running.

Strong model on every cell, but the run is slow and expensive. Switch routine cells to the cheap default. SQL generation rarely benefits from a stronger model; it's the cell that consumes the SQL output that does.

See also

QRYA product of IXEN.