---
url: /quail/introduction.md
description: >-
  Quail 是什么？2026 年 9 月 24 日开源的 AI-SQL 推理引擎（MIT 协议，quail-engine 0.1.0），把 SQL
  查询计划和 LLM 推理当成一个问题联合优化，单张 H100 跑到每分钟 10 亿 token，医疗报告 Join 场景比 vLLM 快 14.04
  倍、成本从 27.03 美元降到 1.93 美元。五分钟搞懂 AI-SQL 这个新物种。
---

# 认识 Quail：一条 SQL 里写中文让大模型逐行判断，为什么能快 14 倍？

先说一件让我自己都觉得离谱的事。

上个月有个朋友找我，他们有 10 万条客服工单，想筛出"用户其实是在抱怨物流而不是产品本身"的那些。这活儿关键词搞不定，规则写不出来，典型的"只有大模型能干"。

他很兴奋地给我看他的方案：`SELECT * FROM tickets WHERE AI.IF("用户在抱怨物流")`，一行 SQL，多优雅。

我多嘴问了一句：跑完多久？

他说：**跑了一夜，没跑完。**

这不是他代码写得烂，也不是模型选得差。这是一整类新 workload 撞上了一堵所有人都还没注意到的墙——**我们用给聊天机器人设计的推理引擎，在跑数据库的活儿。**

然后 2026 年 9 月 24 日，一个叫 **Quail** 的开源项目冒了出来，MIT 协议。它的官方说法很朴素：**同一个最难的查询，精心调优过的 vLLM 要跑 6.84 小时，它跑 29.3 分钟。快 14.04 倍，成本从 27.03 美元降到 1.93 美元。**

我第一反应是不信。看完它的做法之后，我觉得这个数字反而**偏保守**。

## 什么是 Quail

**Quail 全称 QUery-Aware Inference Layer，是 Full Stack Data Lab（Shreya Shankar）与 Modal（Charles Frye）合作开源的 AI-SQL 推理引擎，MIT 协议，PyPI 包名 `quail-engine`，首发版本 0.1.0（要求 Python 3.12，锁定 vLLM 0.26.0）。代码在 github.com/fsdatalab/quail。它不是一个数据库，也不是 vLLM 那种通用推理服务器——它是一个"知道你整条 SQL 长什么样"的推理引擎，把查询计划和模型推理当成同一个优化问题来解。**

要理解它为什么存在，得先说清楚 AI-SQL 是什么。

## 先搞懂一件事：AI-SQL 不是"让大模型写 SQL"

这是最多人搞混的地方，我必须放在最前面。

* **Text-to-SQL**：人说"给我上个月的销售额"，**模型生成一条 SQL**。模型是翻译官。
* **AI-SQL**：人写一条 SQL，SQL 里某个条件**是自然语言，由模型逐行判断真假**。模型是数据库里的一个算子。

长这样：

```sql
-- 找热线索：每个客户画像 × 每个产品描述，让模型判断"这人会不会买这个"
SELECT customers.id, products.id
FROM customers JOIN products ON
AI.IF(
  PROMPT("{customers.profile} might buy this: {products.description}")
)
```

看出恐怖之处了吗？

`AI.IF` 是 **WHERE 里的一个函数**，它对**每一行**都要调一次模型。而 `AI.IF` 放在 JOIN 的 ON 条件里，就是对**笛卡尔积的每一对**调一次模型——1 万个客户 × 1 万个商品 = **一亿次模型调用**，每次输入还好几百 token。

> 一条 SQL 能触发几百万次、每次几千 token 的推理请求。
> 这不是"推理服务"，这是**一次批量计算作业**，却被当成"一堆独立的聊天请求"塞进了推理引擎。

这不是我瞎编的需求。Snowflake 的 Cortex AI、Google BigQuery、Databricks、MotherDuck 全都已经上线了这类 AI 函数，`AI_FILTER` / `AI.IF` / `AI.GENERATE` 各家拼写不同，本质一样。学术界更早就在做：Berkeley 的 DocETL、Stanford 的 LOTUS、MIT 的 Palimpzest、Cornell 的 ThalamusDB，都在琢磨怎么少调几次模型。

但**几乎没人动"推理引擎本身"这一层**。直到 Quail。

## 它有什么特点

### 第一，也是唯一的核心思路：把查询计划和推理一起优化

通用推理引擎（vLLM、SGLang）的处境是**盲的**——请求一个一个进来，它不知道下一个请求是什么，只能做通用优化。

Quail 的处境完全不同：**你先把整条 SQL 交给它，它在执行前就知道全部请求长什么样。**

这个信息差，让一堆原本做不了的优化突然能做了：

* **算子重排**：两个 `AI.IF` 过滤条件，先跑哪一个？当然先跑**选择性高**（能筛掉更多行）的那个——下游直接少算一大半。这是 Hellerstein 和 Stonebraker 几十年前的老手艺，只是现在成本模型里换成了 token 数。
* **Join 顺序 + anchor 选择**：用 System R 那套动态规划搜 Join 顺序，同时决定**哪一侧放在 prompt 前面**当"锚点"——因为前缀相同就能复用 KV 缓存。
* **Speed-of-light 成本模型**：先算出理论上最快能多快（只算 matmul 和 attention），拿它当标尺去衡量实际计划离极限还有多远。

> 以前是"数据库优化完 SQL，把一堆请求丢给推理引擎，各管各的"。
> Quail 是"这俩本来就是一个问题"。
> 这也是为什么它最难的那个查询能快 14 倍，而平均只快 1.84 倍——**Join 越复杂，联合优化的红利越大。**

### 第二，KV 缓存的"回退"而不是"丢弃"，这是最漂亮的一招

一条文档进来，跑完第一个过滤条件，它的 KV 缓存（这篇文档在 GPU 显存里的注意力状态）里包含了：文档本身 + 这个判断条件的 prompt。

vLLM 的做法是：这条请求结束，KV 缓存回收。下一算子还要判断同一篇文档？**重新算一遍。**

Quail 的做法是：

1. 过滤判完 True/False，把**只属于这个条件的那截后缀 KV 回退掉**，文档本身的 KV 留在 HBM 里；
2. 下游算子还需要这篇文档？直接接着用，**零重算**；
3. 不需要了才释放；
4. 显存不够要淘汰时，**先淘汰短文档**——因为注意力开销是长度平方级，长文档重算起来贵得多。

团队专门造了个指标叫 **KV regret**（多算的重复 token 数）。在最难的那个医疗查询上：

| | Quail | vLLM（已调优） |
|---|---|---|
| KV regret | **1800 万** token | 5030 万 token |
| 输入吞吐 | **1900 万** token/秒 | 136 万 token/秒 |
| 耗时 | **29.3 分钟** | 6.84 小时 |
| 单查询成本 | **$1.93** | $27.03 |

那 5000 万 token 的差距，就是 vLLM 一遍又一遍重算同一批医疗报告的代价。

### 第三，Join 用"树注意力"，锚点只算一次

AI Join 的场景是：文档 A 要跟 B1、B2、B3... 几百个候选分别比对。朴素做法是拼几百个 prompt，A 被重复编码几百次。

Quail 把共享同一个锚点的所有伙伴分组，注意力拆成两步：

1. 所有伙伴的 query 对锚点的 KV 做一次**交叉注意力**（锚点只算一次）；
2. 伙伴各自对自己的后缀做因果注意力；
3. 用 log-sum-exp（online-softmax 那套）把两边结果合并。

这和 FlashInfer 的 cascade attention、Hydragen、SpecInfer 是同一个思想家族。区别在于：**那些技术得"猜"哪些前缀相同，Quail 提前就知道了**，所以能省掉一大堆运行时复杂度。

### 第四，把 CPU 从关键路径上赶走

这是最容易被忽略、但在 QUAIL-B 全集上贡献最大的一块。

场景是：请求数百万级、模型很小（几十亿参数）、GPU 很大（H100）——**这根本不在通用推理引擎的设计区间里**。表现就是 GPU 在等 CPU 发请求，利用率上不去。

Quail 的解法：

* tokenizer 换成 Stanford 的 **Gigatoken**（vLLM 自带的 HF tokenizer 在这个量级上就是瓶颈）；
* token ID 存进内存映射的 Arrow 文件；
* 算子间**流式批处理**，像 Apache DataFusion 那样 pull-based，CPU 准备下一批的同时 GPU 在跑当前批，不留空档。

用 Triton 手写了几个融合 kernel（add-RMSNorm 融合 FP8 量化、per-head QK-norm 融合 RoPE），核心 matmul 用 DeepSeek 的 DeepGEMM，注意力用 FlashAttention 3。

还有一个我觉得特别聪明的小优化：\*\*输出头只算 TRUE 和 FALSE 两个 token 的 logits，不算整个词表。\*\*反正你要的只是一个布尔值。

### 第五，架构是"拼"出来的，不是造出来的

这点值得单独说，因为它决定了这项目能不能活下来：

| 层 | 用什么 |
|---|---|
| SQL 解析 | `sqlglot`（支持 snowflake / bigquery 两种方言） |
| 查询计划 | 自研（核心工作量），用 Substrait 序列化 |
| 执行引擎 | 从 vLLM 的 forward 实现 fork 出来改，Triton 写融合 kernel |
| 存储 | `pyarrow`，列式 Arrow |

作者原话大意是：现在做数据库已经不难了（Stonebraker & Pavlo, 2024），关键组件都有可扩展的开源实现，加上 coding agent，拼装变得异常容易。

> 这句话我特别认同，而且它其实是整个项目的潜台词：
> **在推理和数据库交叉的地方，还有大量没被开垦的性能空间，等着人去捡。**

## 场景：它到底在哪些活儿上值这个钱

先把丑话说在前面：\*\*Quail 是 2026 年 9 月 24 日刚开源的研究型项目，版本 0.1.0，没有任何公开的商业化客户案例。\*\*你要找"某某公司用它省了几百万"这种故事，现在没有。

但它公布的 QUAIL-B 基准里那 29 个查询，全都来自真实数据，而且把成本摆得很清楚。这比一个包装过的客户故事更有说服力。

### 场景一：医疗报告 × 不良反应术语的 Join（BIO-4）

5000 份医疗报告，跟 4144 个不良反应术语做 Join，术语集被用了两次。模型 Qwen3 4B FP8，单张 H100。

\*\*29.3 分钟 vs 6.84 小时，$1.93 vs $27.03。\*\*吞吐 1900 万 token/秒——这就是"单卡每分钟 10 亿 token"那个 headline 数字的来源。

放在 Modal 的 H100 定价（$3.9492/GPU-hour）下折算，**每十亿 token 不到 6 分钱**。

### 场景二：10 万条 IMDB 影评，筛"剧透结尾的"（IMDB）

```sql
SELECT r.id FROM reviews r
WHERE AI_FILTER(PROMPT('Does this review discuss the ending?\n\n{0}', r.review))
```

实测跑完的数据：10 万条影评，命中 **16,057** 条，实际消耗 **3249.9 万** token，处理速度 **360.5 文档/秒**，总耗时（含 GPU 冷启动）335 秒，**GPU 成本 $0.3675**。

对照一下：**同样两个过滤条件走 GPT-5 nano 的 API（含缓存价），大约 $1.75，是 Quail 的 4.8 倍。**

### 场景三：Agent trace 分析（AGENT）——它输了的那一局

这部分我必须写出来，因为它比赢的那些更有信息量。

QUAIL-B 里有 2 个基于软件 Agent 运行轨迹的查询。**在这两个查询上，Quail 输给了 vLLM：成本是对方的 2.32 倍。**

原因很直白：Agent trace 里大量请求**前缀是相同的**（同一个系统提示词、同一段上下文），vLLM 的自动前缀缓存（automatic prefix caching）天生就吃这个场景，而 **Quail 目前还不支持跨行的前缀复用**——它只在同一条文档内部复用 KV。

作者没藏这个数据，直接写进了论文，还把它标成"未来工作"。

> 一个开源项目敢把自己输的那一局写进基准报告，并且专门设计了两个查询来暴露自己的短板——
> 我对这种项目的信任度，比那些只放漂亮数字的，高一个数量级。

### 场景四：你已经在用 Snowflake / BigQuery 的 AI 函数

如果你公司已经在用 Snowflake Cortex AI 或 BigQuery 的 `AI.IF` 做批量标注、工单分类、合规筛查，那 Quail 给你的是**一个开源的、可自托管的对照方案**——同样一批活儿，自己拿开源小模型跑，成本可能差一个数量级。

它支持 **Snowflake 和 BigQuery 两种方言的拼写**（`AI_FILTER` 和 `AI.IF` 都能解析），所以你现有的 SQL 大概率不用改就能试。

## 初体验：怎么上手

最省事的方式是用 Modal 直接跑，不用自己有 GPU：

```bash
uvx modal run try_quail.py
```

```python
import modal

app = modal.App("try-quail")
image = (
    modal.Image.from_registry("nvidia/cuda:13.0.1-devel-ubuntu24.04", add_python="3.12")
    .entrypoint([])
    .apt_install("git")
    .uv_pip_install("quail-engine==0.1.0")
)

@app.function(gpu="H100!", image=image, timeout=600)
def run(sql=None, documents=None):
    from datasets import load_dataset
    import pyarrow as pa
    import quail

    if sql is None:
        sql = """
            SELECT r.id
            FROM reviews r
            WHERE AI_FILTER(PROMPT('Does this review discuss the ending?\n\n{0}', r.review))
        """

    imdb = load_dataset("stanfordnlp/imdb")["train"]
    documents = pa.table({
        "id": pa.array(f"review-{i}" for i in range(len(imdb))),
        "review": imdb.data.table.column("text"),
    })

    config = quail.EngineConfig(
        gpus=1,
        model="qwen3-4b-fp8",
        backend="quail",
        device="h100-sxm",
    )

    with quail.Session(config) as session:
        session.register("reviews", quail.DocumentProvider.from_table(documents, id_col="id"))
        result = session.sql(sql).run()

    print(result.collect())
    print(result.report)
```

如果你自己有卡，Python API 就四步：**注册数据**（Arrow 表或 dataset）→ **写 SQL 或 Python 查询构造器**→ **`session.sql(sql).run()`** → **`result.collect()`**。

几个上手时容易踩的点：

* 当前版本只支持 **AI 过滤、AI Join、投影和 LIMIT**。**没有 GROUP BY，没有聚合**，语义分组还在路线图上；
* 数据是**注册进内存 Arrow 表**的，官方假设你事先从 S3 或 Modal Volumes 拉下来，它自己不管存储；
* 你可以给算子**显式传 selectivity（预期通过率）和 anchor（Join 锚点）**，不传的话它就按你写的顺序老实执行——**想吃到优化红利，最好传 selectivity**；
* 模型列表目前很窄，官方基准全用 **Qwen3 4B FP8**，KV 用 BF16。

## 进阶

如果这篇文章你只记住一件事，我希望是这个判断：

**AI 的推理 workload 正在分裂，而我们还在用一套引擎打所有仗。**

过去两年整个推理优化行业的目标函数高度一致：**降低单请求延迟、提高单用户吞吐**，因为服务对象是聊天和 Agent。但"给 10 万行数据每行做一次判断"这件事的目标函数完全不同——**总吞吐和总成本才是唯一指标，延迟根本不重要，而且请求在执行前就全部已知。**

用前者的引擎跑后者的活儿，就像用出租车送快递：能送到，但贵得离谱。Quail 的贡献不是发明了多少新 kernel，而是**指出了这个 workload 分类，并给出了第一个开源参考实现**。

冷水照例要泼，这次泼三盆，都很实在：

\*\*第一，1.84 倍这个平均数，别当成你的收益。\*\*拆开看：对比"朴素 vLLM"是 1.84 倍，但对比"已经做了算子间流水线的 vLLM"，**只有 1.12 倍**。也就是说，全集上的收益大部分来自"消除 CPU 调度开销"这一项，而这一项你自己写点批处理程序也能捞回来一部分。**真正拉开数量级的是 Join 密集场景**（BIO 数据集上 8.72 倍的成本优势），如果你的活儿只是简单过滤，提升可能没你想象的大。

\*\*第二，它离自己的理论极限还有 3.35 倍。\*\*团队算了 speed-of-light 估计：整个 QUAIL-B 理论最快 491 秒，Quail 跑了 1644 秒。作者自己说"还有很大空间"。**换句话说，现在的 Quail 是个不错的起点，不是终点。**

\*\*第三，功能面还窄，别急着往生产塞。\*\*0.1.0 版本，无聚合、无跨行前缀缓存、模型支持少、只支持单机单卡到单机多卡。作者明确说了"我们还在 actively building"。

我的建议很具体：\*\*如果你现在在用 Snowflake / BigQuery 的 AI 函数做批量任务，先把最贵的那条查询导出来，用 Quail 跑一遍同样的语义，对比账单。\*\*这个实验半天就能做完，而结论可能直接决定你明年这笔预算怎么花。

再往深一层，我建议你去读两篇原文：Modal 那篇博客（从推理工程师视角讲 kernel 和 KV 管理），和 Full Stack Data Lab 那篇（从数据库工程师视角讲查询计划）。**这两篇放在一起看，你会理解为什么"数据库的人"和"推理的人"过去两年几乎不说话——而最大的红利恰恰在他们中间那条缝里。**

至于 AI-SQL 会不会变成数据库的标配能力（Snowflake、BigQuery、Databricks、MotherDuck 已经全上了，说明需求是真的），我的看法是：\*\*已经是了。\*\*问题只是这活儿最后由云厂商的闭源函数做，还是由你自己拿开源模型做——Quail 押注的是后者，而且押得挺聪明。

更多开源技术干货和学习资料，关注公众号「遇码」，领取专属福利。
