/ Модель

Характеристики

Контекст
262 144 токена
Лицензия
Apache 2.0
Архитектура
qwen3_5 · dense
Базовая модель
Qwen3.5-2B
Опубликована
11 авг 2026

qwen-3.5-sql-27B-Distill-2B

Генерация текстаТекст → текст4 профессии

Компактная модель на базе Qwen3.5-2B, дообученная для генерации проверяемых SQL-запросов SQLite по вопросам на естественном языке.

266скачиваний за 30 дней3лайкавеса обновлены5 сен 2026

Бенчмарки

Как модель справилась с задачами пользователей ailist и что о ней публикуют открытые лидерборды

Тесты пользователейпока нет

Никто ещё не опубликовал тест этой модели. Соберите бенчмарк из своих задач — результат появится здесь.

  1. Добавьте модель в бенчмарк

    Вместе с другими моделями категории «Текст» — сравнение идёт внутри одной категории.

  2. Опишите свои задачи

    Напишите запросы, при необходимости приложите файлы и эталонные ответы.

  3. Запустите и опубликуйте

    Модели ответят на каждую задачу, судья оценит ответы. Опубликованный результат появится на этой странице.

Публичные оценки

Из открытых лидербордов. Сравнивайте результаты одного теста при одинаковых условиях — отсутствие оценки не значит, что модель хуже.

В подключённых источниках результатов для этой модели пока нет.

Что умеет модель

Описание составлено по карточке модели и метаданным Hugging Face

AlioLeuchtmann разработал эту плотную модель на 2 млрд параметров для преобразования вопросов на естественном языке в SQL-запросы к базам SQLite. Она создана дообучением Qwen/Qwen3.5-2B с помощью дистиллированных от модели-учителя Qwen на 27 млрд параметров трасс рассуждений, проверенных выполнением SQL. Модель принимает схему базы данных, примеры строк, вопрос и подсказку с контекстом; отвечает структурированным анализом и SQL в блоке кода. Для извлечения запроса следует брать последний блок SQL.

Модель рассчитана на аналитические вопросы в стиле BIRD; автор сообщает об официальной оценке на скрытом тестовом наборе BIRD: точность выполнения 68,47% при голосовании по семи вариантам. Рекомендации по использованию включают три примера строк на таблицу, описания столбцов и отключённый режим thinking. Лицензия — Apache-2.0. Модель не предназначена для общего диалога; на сложных задачах её точность ограничена, а результат бенчмарка предполагает голосование по нескольким генерациям.

Сценарии применения

  • генерация SQL-запросов SQLite по вопросам на естественном языке
  • ответы на аналитические вопросы к реляционной базе данных
  • создание SQL для баз данных с подсказками и описаниями столбцов

Ограничения

Модель специализирована для SQLite и сценариев в стиле BIRD, а не для общего чата; для лучших результатов нужны схема, примеры строк и подходящие подсказки. На сложном уровне BIRD точность выполнения составляет около 50,9%, а опубликованный общий результат использует голосование по семи генерациям.

Для каких профессий подходит4

Разделы каталога профессий, в задачах которых используется эта модель

Все профессии

Карточка модели

README от автора на Hugging Face, как он его опубликовал

Открыть на Hugging Face

Qwen3.5-2B · StructCoT SQL (27B-Distilled)

The smallest model in the top tier of the BIRD single-model leaderboard A 2B-parameter text-to-SQL model that outperforms models over 500× its size on the official BIRD benchmark.

Qwen3.5-2B fine-tuned for SQLite text-to-SQL through execution-verified structured chain-of-thought distillation from a Qwen 27B teacher. Evaluated officially by the BIRD team on the hidden test set.

  • No reinforcement learning — no GRPO/PPO/DPO stage; the entire gain comes from execution-verified rejection-sampled distillation
  • No test-time thinking — non-thinking decoding with a compact structured analysis (~500 output tokens), not long reasoning chains;

Official BIRD test-set results (https://bird-bench.github.io/)

Evaluated by the BIRD team (majority@7 self-consistency, single model, single A100):

metricsimple (949)moderate (555)challenging (285)total (1789)
Execution Accuracy (EX)77.1362.7050.8868.47
Soft F177.4663.8753.4169.41
R-VES69.2555.9346.4761.49

Size-for-score context (official BIRD test EX, Single Trained Model Track)

modelsizetest EX
Infly-RL-SQL-32B (inftech.ai)32B70.60*
Arctic-Text2SQL-R1-7B (Snowflake)7B70.43*
Claude Opus 4.6 (baseline)frontier API70.15
XiYanSQL-QwenCoder-32B (Alibaba)32B69.03*
Arctic-ExCoT-70B (Snowflake)70B68.53
this model2B68.47*
Arctic-ExCoT-32B (Snowflake)32B68.19
Qwen3-Coder-480B-A35B (baseline)480B (MoE)68.14
Align-SQL-7B7B67.97*
Claude 4.5 Sonnet (baseline)frontier API66.85
Align-SQL-3B3B66.41*
GLM-4.7 (baseline)frontier62.94
DeepSeek-R1 (baseline)671B (MoE)60.93
Kimi-K2-Thinking (baseline)~1T (MoE)59.87

* Few (1–7 candidates) · ** Many (8–32) · *** Scale (>32) · no mark = no self-consistency

At 2B parameters this model ties a 70B specialist, and outperforms frontier general-purpose LLMs — including Claude 4.5 Sonnet, DeepSeek-R1, and Kimi-K2-Thinking — as well as GPT-4o-based multi-stage pipelines and is only beaten by sophisticated specialists at least 2.5x times its Size. (Frontier-LLM rows are their official BIRD baseline entries; this model is a task-specialized fine-tune with self-consistency @7, declared as "Few" on the single-model track.)

Why this matters: distillation as a path to expert small models

This model is evidence for a broader thesis: in specialized domains, knowledge distillation can compress most of a large model's task competence into a model orders of magnitude smaller — here, ~93% of a 27B teacher inside 2B parameters, with no reinforcement learning and no test-time reasoning chains. The key enabler is that text-to-SQL is a verifiable domain: every candidate trace can be executed against the real database and checked against the gold result, so the training corpus can be filtered to contain only demonstrably correct reasoning. Wherever such a verifier exists — SQL execution, compilers, type checkers, simulators — the same recipe applies: sample the teacher broadly, keep only what provably works, and fine-tune small.

The practical upside is significant. A 2B specialist runs on a single consumer GPU (or CPU/edge hardware), answers in a few hundred tokens instead of thousand-token thinking chains, keeps data on-premises, and costs a fraction of a cent per API call — while, on its domain, outperforming general-purpose models hundreds of times its size. General frontier models remain the right tool for open-ended work, but for a fixed, well-defined task, this result suggests the efficient frontier is not a bigger generalist — it is a small model taught by one.

How it was trained

Every training target is an execution-verified chain-of-thought trace: a trace only enters the corpus if its final SQL, executed against the real database, reproduces the gold result set. No unverified text is ever trained on.

Stage 1 — Distillation SFT. 50,572 structured-CoT traces rejection-sampled from a Qwen 27B teacher over BIRD train, Spider, and synthetic schema corpora (multiple sampling rounds per item; longest correct trace kept). Each trace follows a 7-section template: question/hint mapping → schema selection → join path → filters → aggregation → edge checks → final checklist + SQL. 3 epochs, lr 2e-5, effective batch 32, NEFTune 5, bf16.

Stage 2 — Column-description anneal. BIRD databases ship per-column descriptions (database_description/*.csv); the schema prompt is augmented with them as comment blocks, and the model is annealed for 1 epoch at lr 3e-6 (cosine→0) on BIRD-train traces re-paired with these enriched prompts, plus 10% original-format replay. This stage alone adds ≈ +2.5 EX.

How to use it

The model expects the OmniSQL-style prompt (schema DDL + example rows + question + evidence hint) and answers with a structured analysis ending in a fenced SQL block — always extract the last sql fence. Generate in non-thinking mode.

"""Prompting qwen-3.5-sql-27B-Distill-2B (BIRD-style text-to-SQL)."""
import re, sqlite3
from collections import Counter
from transformers import AutoTokenizer
from vllm import LLM, SamplingParams

MODEL = "AlioLeuchtmann/qwen-3.5-sql-27B-Distill-2B"
BT = "`" * 3                      # code-fence marker used inside the prompt template
FENCE = re.compile(rf"{BT}(?:sqlite|sql)?\s*(.*?){BT}", re.S)

TEMPLATE = """Task Overview:
You are a data science expert. Below, you are provided with a database schema and a natural language question. Your task is to understand the schema and generate a valid SQL query to answer the question.

Database Engine:
SQLite

Database Schema:
{db_details}
This schema describes the database's structure, including tables, columns, primary keys, foreign keys, and any relevant relationships or constraints.

Question:
{question}

Instructions:
- Make sure you only output the information that is asked in the question. If the question asks for a specific column, make sure to only include that column in the SELECT clause, nothing more.
- The generated query should return all of the information asked in the question without any missing or extra information.
- Before generating the final SQL query, please think through the steps of how to write the query.

Output Format:
In your answer, please enclose the generated SQL query in a code block:
{fence}sql
-- Your SQL query
{fence}

Take a deep breath and think step by step to find the correct SQL query."""


def build_schema(db_path, descriptions=None, num_rows=3, max_cell=64):
    """DDL + optional column-description comments + a few example rows per table."""
    conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
    conn.text_factory = lambda b: b.decode("utf-8", errors="replace")
    cur = conn.cursor()
    cur.execute("SELECT name, sql FROM sqlite_master "
                "WHERE type='table' AND name != 'sqlite_sequence'")
    blocks = []
    for table, ddl in cur.fetchall():
        block = (ddl or "").strip()

        # column descriptions (BIRD ships these in database_description/*.csv)
        desc = (descriptions or {}).get(table.lower(), {})
        if desc:
            cols = [c[1] for c in cur.execute(f'PRAGMA table_info("{table}")')]
            lines = [f"-- {c}: {desc[c.lower()]}" for c in cols if c.lower() in desc]
            if lines:
                block += f"\n/* Column descriptions for {table}:\n" + "\n".join(lines) + "\n*/"

        # example rows
        try:
            cur.execute(f'SELECT * FROM "{table}" LIMIT {num_rows}')
            rows, names = cur.fetchall(), [d[0] for d in cur.description]
            if rows:
                def clip(v):
                    s = "NULL" if v is None else str(v).replace("\n", " ")
                    return s[:max_cell] + "..." if len(s) > max_cell else s
                header = " | ".join(names)
                body = "\n".join(" | ".join(clip(v) for v in r) for r in rows)
                block += (f"\n/* {len(rows)} example rows from {table}:\n{header}\n"
                          f"{'-' * min(len(header), 120)}\n{body}\n*/")
        except sqlite3.OperationalError:
            pass
        blocks.append(block)
    conn.close()
    return "\n\n".join(blocks)


def build_prompt(schema, question, evidence=""):
    """Evidence/hint is appended to the question, exactly as in BIRD."""
    if evidence and evidence.strip().lower() not in ("", "none"):
        question = f"{question}\n\nHint: {evidence}"
    return TEMPLATE.format(db_details=schema, question=question, fence=BT)


def extract_sql(text):
    """The model emits a structured analysis first — always take the LAST fence."""
    blocks = FENCE.findall(text or "")
    return blocks[-1].strip() if blocks else ""


# --------------------------------------------------------------- inference
tok = AutoTokenizer.from_pretrained(MODEL)
llm = LLM(model=MODEL, dtype="bfloat16", max_model_len=16384)


def chat(prompt):
    return tok.apply_chat_template(
        [{"role": "user", "content": prompt}],
        tokenize=False, add_generation_prompt=True,
        enable_thinking=False,        # non-thinking mode: the model is trained this way
    )


def generate_sql(prompt):
    """Greedy decoding — one query."""
    out = llm.generate([chat(prompt)], SamplingParams(temperature=0.0, max_tokens=2048))
    return extract_sql(out[0].outputs[0].text)


def majority_at_7(prompt, db_path, k=6, temperature=0.6):
    """Self-consistency: 1 greedy + k sampled candidates, voting by executed result set.
    This is how the reported scores were produced (~+5 EX over greedy)."""
    greedy = llm.generate([chat(prompt)], SamplingParams(temperature=0.0, max_tokens=2048))
    sampled = llm.generate([chat(prompt)],
                           SamplingParams(n=k, temperature=temperature, max_tokens=2048))
    candidates = [extract_sql(greedy[0].outputs[0].text)] + \
                 [extract_sql(o.text) for o in sampled[0].outputs]

    def run(sql):
        try:
            conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
            conn.text_factory = lambda b: b.decode("utf-8", errors="replace")
            rows = frozenset(conn.execute(sql).fetchall())
            conn.close()
            return rows
        except Exception:
            return None

    results = {sql: run(sql) for sql in dict.fromkeys(candidates)}   # dedupe, keep vote weight
    votes = Counter()
    for sql in candidates:
        if results[sql] is not None:
            votes[results[sql]] += 1
    if not votes:
        return candidates[0]                                         # nothing ran: greedy fallback
    winner = votes.most_common(1)[0][0]
    return next(sql for sql in candidates if results.get(sql) == winner)


# --------------------------------------------------------------- example
db = "california_schools.sqlite"
prompt = build_prompt(
    build_schema(db),
    "What is the highest eligible free rate for K-12 students in Alameda County?",
    evidence="eligible free rate for K-12 = `Free Meal Count (K-12)` / `Enrollment (K-12)`",
)

print(generate_sql(prompt))            # greedy
print(majority_at_7(prompt, db))       # self-consistency (reported setting)

Tips for best results

  • Take the last ```sql fence. Everything before it is the model's reasoning; naive first-match extraction will grab a fragment from the analysis.
  • Include 3 example rows per table. They are part of the training-time prompt format.
  • Pass column descriptions when the database has them. BIRD ships them in database_description/*.csv; the model was explicitly trained to exploit them (worth ≈ +1.4 EX on its own).
  • Keep enable_thinking=False. The whole lineage is trained on plain structured CoT, not on <think> traces.
  • Majority@7 voting by executed result set gives ≈ +5 EX over greedy — that is the setting used for the reported benchmark numbers.

Intended use & limitations

Built for SQLite text-to-SQL (BIRD-style analytical questions with evidence hints). Not instruction-tuned for general chat. Performance on the challenging tier (50.9 EX) still trails large models — complex multi-step reasoning remains the 2B's bound.

Acknowledgements

Built on Qwen3.5-2B with a Qwen 27B teacher. Evaluated by the BIRD team (bird-bench.github.io). Developed by Alio Leuchtmann.

Как запустить

На своей GPU в ailist. Цена — по текущим предложениям провайдеров

GPU в ailist

Универсальный рантайм

Можно запустить

Подбираем GPU…

Класс архитектуры
Qwen3_5ForConditionalGeneration
Ревизия весов
fd4827e

0 моделей