sql-specialist-mcp
sql-specialist-mcp
Небольшая дообученная модель с открытыми весами, которая отвечает на вопросы на естественном языке о базе данных SQLite и работает как MCP-инструмент — любой MCP-клиент (Claude Desktop, Claude Code, кастомные агенты) может вызывать его напрямую. В основе лежит eval-харнесс, измеряющий точность исполнения: он сравнивает специалиста с запросами к frontier-модели по точности, задержке и стоимости.
Смысл проекта не в том, чтобы «сделать демо text-to-SQL» — а в том, чтобы показать части LLM-инжиниринга, которые лежат ниже промптирования: взять маленькую модель, адаптировать её под одну задачу через LoRA, эффективно обслуживать и доказать с помощью настоящего eval-а, основанного на исполнении, что дешёвый специалист конкурентоспособен с запросами к frontier-модели (или превосходит их) для этой узкой задачи.
Попробуйте интерактивное демо — пройдите все 28 реальных eval-вопросов и посмотрите, какой SQL реально сгенерировал специалист, его задержку и результирующие строки рядом с frontier-базлайном. Устанавливать ничего не нужно.
Зачем это существует
Большинство «AI-портфолио» проектов text-to-SQL — это быстрые старты на LangChain. Здесь два отличия:
Eval строгий, а не «по ощущениям». Каждый золотой запрос исполняется против базы данных на этапе сборки датасета (139/139 проверено), а скоринг сравнивает результирующие наборы, а не текст запроса — семантически корректный запрос с другим порядком колонок всё равно получает «верно». Предиктор, который просто повторяет золотой SQL, показывает результат 100%; предиктор, который всегда возвращает заведомо неверный запрос, показывает 0%. Оба проверены как sanity-тесты (
tests/test_harness_oracle.py), так что корректность самого харнесса не постулируется.Это полезный инструмент, а не просто демо-репозиторий. Дообученная модель доступна как настоящий MCP-инструмент (
nl_to_sql) — наведите Claude Desktop или Claude Code наmcp_server/server.py, и он сможет реально выполнять запросы к базе данных в ходе разговора.
Related MCP server: mcp-sqlite-chat
Результаты
Полный конвейер запущен end-to-end на реальном железе с обеих сторон: реальное LoRA-обучение, реальное слияние, реальная GGUF-квантование, реальный Ollama-сервер, реальный eval — а также настоящий фронтир-базлайн через живой Claude API.
Базовая модель: Qwen/Qwen2.5-Coder-0.5B-Instruct (выбрана ради быстрой итерации на ноутбуке; см. Fine-tuning ниже о пути к 1.5B).
Предиктор | Точность | n | p50 задержка | p95 задержка | Стоимость / 1 тыс. вызовов |
frontier: Claude Haiku 4.5 (промпт) | 53.6% | 28 | 1055ms | 1884ms | $1.06 |
sql-specialist (дообучен, квантован, локально) | 92.9% | 28 | 207ms | 371ms | $0.00 |
Читайте это с оговоркой, а не с заголовком. Я вручную просмотрел все 13 измеренных «провалов» Claude Haiku на этом eval-наборе: ни один из них не был логической ошибкой в SQL. Все 13 — рассинхрон по выбору колонок или порядку строк: например, вывод (name, email), когда золотым ответом был только (name), или верные строки в другом порядке, чем курс по ORDER BY, которого исходный вопрос вообще не задавал. Строгая метрика execution-accuracy (в eval/execution.py сравниваются строки результата колонка-к-колонке) оценивает это точно так же, как действительно неверный запрос, чего дообученный специалист никогда не дасть, потому что он запомнил стандарты этого датасета из 111 обучающих примеров — а фронтир-модель, вызванная zero-shot, просто не может об этом знать. Полная порций-по-провалам таксономия в COMPARISON.md.
Итак: разрыв по точности реален, но отчасти это артефакт того, что оценивает eval, а не чисто разрыв в рассуждениях. Разрыв по задержке и стоимости — не артефакт — 207ms/локально/бесплатно против 1055ms/$1.06 за 1 тыс. вызовов — это фактический результат запуска локально-квановой 0.5B модели вместо вызова API, и именно на этом сравнении основана посылка проекта.
Собственные 2 провала специалиста (из 28) были настоящими логическими ошибками, а не несоответствием форматирования: галлюцинирование правдоподобной колонки orders.total, которой нет в этой схеме, и исключение квалификатора таблицы в одном многократном SELECT. Обучение сходилось стабильно на 3 эпохах (eval loss 0.060 → 0.048 → 0.008), а квантованизация (988MB f16 → 373MB q4_k_m) обслуживается через Ollama примерно за 200мс..
Что здесь реально
Здесь важно быть честным больше, чем может показаться — это разница между проектом, которому рекрутёр может доверять, и тем, что выглядит как маркетинг.
Генерация базы и датасета доказуемо корректны.
shopsphere.dbсоздаётся детерминированно (сид = 42); каждая из 139 золотых пар (вопрос, SQL) вdata/*.jsonlсоздаётся из параметрических шаблонов и выполняется против реальной базы на этапе сборки — шаблон, дающий невалидный SQL, проваливает сборку, а не молча выдаёт неверную метку.Корректность eval-харнеса сама протестирована, а не принята постулатом —
tests/test_harness_oracle.pyутверждает, что оракуляровый предиктор (возвращающий золотой SQL дословно) даёт ровно 100%, а умышленно неверный предикков даёт ~0%, прежде чем чьему-то числу доверяют.Execution-accuracy, а не сравнение строк.
eval/execution.pyсравнивает результирующие множества (не учитывая порядок, если только в золотом запросе нетORDER BY) — запрос, написанный иначе, но семантически эквивалентный, всё равно засчитывается как корректный.Дообучение реальное, на этой машине, с подтверждённой сходимости. LoRA (8.8M обучаемых параметров, 1.75% от модели) за 3 эпохи, eval loss монотонно снижается на каждой эпохе. См. Engineering notes ниже о двух реальных багах, найденных и исправленных по пути.
SQL-выполнение настоящим образом песорчено, а не просто проинструктировано «вести себя хорошо»: read-запросы валидируются с помощью regex-списка разрешённых и выполняются на настоящем read-only SQLite-соединении (
mode=roна уровне ОС) — даже баг в regex-защите не приведёт к записи. Это важно не только для eval-харнеса, потому что та же защита работает в MCP-сервере, где SQL приходит от модели, отвечающей на вопрос агента, а не из курируемого eval-набора.MCP-сервер — это реальный вызываемый инструмент с настоящим дообученной моделью, проверено end-to-end:
nl_to_sql("Какие сотрудники не имеют назначенного менеджера?")→ генерация SQL через квантованную модель на Ollama → выполнение запроса read-only → возвращает настоящие строки → пишет задержку/стоимость в observability.Observability реализована самостоятельно и не имеет зависимостей —
observability/logger.pyлогирует каждый вызов (задержку, токены, примерную стоимость, успех/неуспех) в локальный файл SQLite, без стороннего аккаунта, по той же схеме, что иpr-review-agent.Frontier-база тоже настоящая —
eval/baseline_frontier.pyделал запросы к живому Claude API (Claude Haiku 4.5), а не только через красивый импорт. Его «провалы» оказались реальной находкой для методологии evala — см. Результаты выше иождения.
Инженерные заметки: два реальных бага, найденных при реальном запуске
Фактическое выполнение дообучения (а не оставление его в теории) выявило два настоящих бага с памятью в PyTorch, оба исправлены в текущем коде:
Бесконечный рост кэшем MPS. Обучение на Apple Silicon через MPS-задний план
transformers.Trainerприводило к раздуванию процесса до 23GB RSS и зависание, из-за динамического добавления padding по батчам — каждая уникальная форма (batch, seq_len) получает собственный памятьpool в MPS-аллокаторе PyTorch, который не возвращает OSS-память. Исправление:--device cpuвfinetune.py, и, в фундаменталь, фиксированная длина padding (ниже), чтобы этот класс багов не повторился на любом бакенде.Обращение с Trainer/DataLoader, а не сама модель. Непосредственнная прямая propagation+обратная propagation показала 1.6 секунды на примере; тот же расчёт через
transformers.Trainerпростаивал по несколько минут между логами без соответствующей нагрузки. Причина — изолировать фактическую модель+LoRA с ручным замером времени, прежде чем принять, что баг в коде модели. Исправление: заменитьTrainerна цикл обучения околоставим вручную (~40 строк) вtraining/finetune.py— та же LoRA-установка, прямой контроль над циклом батчей, без запредельных оверхейдов. Также перевели сборку батчей с динамического на фикированную длину padding (все батчи одинаковой формы) — это отдельно исправило паттерн фрагментации аллокатора из бага #1.
Ни то, ни другое — не в обходит и not workaround — оба видны в training/finetune.py как единственная реализация, а не как альтернативный путь.
Архитектура
data/build_dataset.py ──▶ data/{train,eval}.jsonl (139 examples, template-generated,
every gold SQL executed at build time)
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
training/finetune.py eval/baseline_frontier.py tests/test_harness_oracle.py
(LoRA on a small (prompt Claude Haiku/ (sanity-checks the harness
open model) Sonnet as the baseline) itself before trusting scores)
│ │
▼ │
training/merge_and_quantize.py
│ │
▼ ▼
serving/ollama_predictor.py ──┴──▶ eval/harness.py ──▶ eval/report.py ──▶ COMPARISON.md
│ (execution-accuracy scoring,
│ same logic for every predictor)
▼
mcp_server/server.py (nl_to_sql tool -- installable in Claude Desktop/Code)
│
▼
observability/logger.py (latency, tokens, cost -- local SQLite, no external account)Структура проекта
schema/ synthetic "ShopSphere" e-commerce DB (7 tables) + seeded generator
data/ templated gold (question, SQL) dataset -- every query build-time validated
eval/ execution-accuracy harness, frontier baseline, comparison report
training/ LoRA fine-tuning pipeline + LoRA-merge/quantize script
serving/ Ollama-backed and in-process HF predictors, Ollama Modelfile template
mcp_server/ the installable MCP tool (nl_to_sql)
observability/ self-built call logging (latency/tokens/cost), no external account
tests/ harness sanity checks (oracle predictor must score 100%)Установка
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # base: anthropic, mcp, requests
python schema/generate_data.py # build the seeded database
python data/build_dataset.py # build + validate the gold dataset
python tests/test_harness_oracle.py # confirm the eval harness itself is soundrequirements-train.txt добавляет torch/transformers/peft/trl для пути fine-tuning — тяжелее, держится отдельно, чтобы путь eval/serving/MCP ставился быстро.
Запуск полного пайплайна
1. Baseline на fронтире (требуется ANTHROPIC_API_KEY):
export ANTHROPIC_API_KEY="..."
python -m eval.baseline_frontier --model claude-haiku-4-5
# writes eval/results_claude-haiku-4-5.json2. Fine-tune специалиста (это то, что реально было запущено для получения результатов выше — ~15 минут активного вычисления на CPU ноутбука, хотя wall clock сильно depends на нагрузке; GPU намного быстрее — см. ниже):
pip install -r requirements-train.txt
python -m training.finetune --base-model Qwen/Qwen2.5-Coder-0.5B-Instruct --device cpu
python -m training.merge_and_quantize --base-model Qwen/Qwen2.5-Coder-0.5B-Instruct
# then follow the printed llama.cpp + ollama create instructions3. Замерить специалиста так же, как бейзлайновый путь:
python -c "
from eval.harness import run_eval, report_to_dict
from serving.ollama_predictor import OllamaPredictor
import json
report = run_eval(OllamaPredictor())
json.dump(report_to_dict(report), open('eval/results_specialist.json', 'w'), indent=2)
"4. Сгенерировать отчёт по сравнению:
python -m eval.report eval/results_claude-haiku-4-5.json eval/results_specialist.jsonТюнинг: масштабирование
Uказанные выше результаты используют Qwen2.5-Coder-0.5B-Instruct на CPU — для быстрой локальной итерации. training/finetune.py --base-model принимает любую HF causal-LM репо (или локальный каталог) — Qwen2.5-Coder-1.5B-Instruct — это логичная замена для лучшего качества, и один достаточноGPU (хватит T4 для этого размера датасета) обучает любой размер за пару минут вместо ~15:
pip install -r requirements-train.txt
python -m training.finetune \
--base-model Qwen/Qwen2.5-Coder-1.5B-Instruct \
--epochs 3--device {cuda,mps,cpu} переопределяет автоопределение. MPS на Apple Silicon определяется автоматически, но пока не рекомендуется для этой задачи — см. Engineering notes выше.
MCP-сервер
# Backend defaults to a locally-served model via Ollama:
python -m mcp_server.server
# Or run against a prompted frontier model instead (no fine-tune needed --
# useful for trying the tool before training anything):
SQL_SPECIALIST_BACKEND=frontier SQL_SPECIALIST_MODEL=claude-haiku-4-5 \
ANTHROPIC_API_KEY=... python -m mcp_server.serverДобавьте в MCP-конфиг Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"sql-specialist": {
"command": "/absolute/path/to/sql-specialist-mcp/.venv/bin/python",
"args": ["-m", "mcp_server.server"],
"cwd": "/absolute/path/to/sql-specialist-mcp"
}
}
}Затем спросите Claude что-то вроде «С помощью инструмента sql-specialist, какие клиенты никогда не делали заказ?» — он вызывает nl_to_sql, получает реальные строки из базы и отвечает на основе фактических данных..
Безопасность
SQL-выполнение доступно только для чтения на двух независимых уровнях: regex-правило, разрешающее только
SELECT/WITH, а также настоящая уровня ОС за RZ-соединение SQLite (file:...?mode=ro) — второй уровень надёжности.MCP-сервер никогда не выполняет запрос, если он не прошёл проверку, независимо от того, что попросили модель или вызывающий агент.
В репозитории нет секретов.
ANTHROPIC_API_KEYчитается только из окружения.
Что я построил бы дальше
Нормализовать eval для superset-колонок — считать предсказание корректным, если значения требуемых золотым колонок присутствуют, а не требовать точного совпадения колонка-к-колонке. Это фикс, который заявлен в «Таксономия ошибок» в
COMPARISON.md; он очень наверноем закроет большую часть измеренного разрыва 53.6% → 92.9% и даст сравнение, которое изолирует собственно способность рассуждать от подгонки под стандарты.Запустить
eval/baseline_frontier.pyи против Claude Sonnet — чтобы точка сравнения была сильнее (Haiku — это дешёвый/быстрый уровень; Sonnet — вопрос «насколько сама по себе сила модели закрывает разрыв»).Дообучить
Qwen2.5-Coder-1.5B-Instructна GPU и сравнить точность с 0.5B результатом 92.9% — чтобы напрямую количественно оценить tradeoff размера и качества.DPO по направлению двух известных fail-мод специалиста (галлюцинируемые колонки, пропажа квалаifiers таблиц в multi-join) — теперь, когда реальные данные про провалы естьи-точается.
vLLM-serving для измерения пропускной способности в сравнении с каналом Ollama/GGUF.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables natural language database queries by combining Ollama's language models with SQLite database access through an MCP server.
- FlicenseNot gradedqualityCmaintenanceEnables querying and managing a SQLite database using natural language, with an MCP server and Groq LLM.
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to query a SQLite database using natural language through the Model Context Protocol (MCP). Includes security guardrails that block destructive SQL operations.
- AlicenseNot gradedqualityDmaintenanceMCP tool server providing SQLite database access for AI agents.MIT
Related MCP Connectors
GibsonAI MCP server: manage your databases with natural language
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Free OpenAI-compatible inference with signed provenance receipts and 3 focused MCP tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Eshanya1/sql-specialist-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server