nl-sql / app /i18n.py
liovina's picture
Deploy NL_SQL HEAD to HF Space (tracked files only)
4e1037f verified
Raw
History Blame Contribute Delete
17 kB
"""I18N strings + translation helper for the Streamlit UI.
Chrome-level strings only. Sample questions stay in their natural
language — the pipeline handles EN + RU both, the toggle only flips
the surrounding UI copy.
"""
# Bilingual UI mixes Cyrillic and Latin in `I18N["ru"]` — silence the
# ambiguous-glyph lint at module scope.
# ruff: noqa: RUF001
from __future__ import annotations
from typing import Any
import streamlit as st
I18N: dict[str, dict[str, str]] = {
"en": {
"page_title": "NL → SQL",
"tagline": "Natural language in. SQL out. Answer rendered in whichever shape fits the question.",
"lang_label": "Language",
"lang_en": "EN",
"lang_ru": "RU",
"metric_kicker": "Chinook business workload",
"metric_value": "60 / 60 correct",
"metric_percent": "100%",
"metric_caption": "30 dev + 30 held-out, balanced split, all ten query categories at 100% on the free-tier codestral pipeline.",
"research_kicker": "BIRD Mini-Dev research benchmark",
"research_value": "61.5% / 200",
"research_short": "Reproducible single-run (codestral, $0). With eval-only hints, the same run scores 62.5%.",
"methodology_label": "How the score was reached",
"research_caption": (
"This demo runs the reproducible pipeline — 61.5% EA, one free-tier codestral pass, "
"no benchmark rescue hints (they are off by default; switching them on takes the same "
"run to 62.5%). The project archive also holds eval-only composites — merges of some "
"twenty voting runs across other providers with those hints on top. They are not a "
"pipeline configuration, do not reproduce, and are not served here. "
"Eval hybrid pipeline: "
"<span class='nl-term' title='Mistral codestral-latest — SQL-specialised generation model, free tier'>codestral</span> + "
"<span class='nl-term' title='Anthropic Claude 4.5 Sonnet via Perplexity Pro browser bridge — used on the hard tier'>Sonnet 4.6 bridge</span> + "
"<span class='nl-term' title='Per-failure re-prompt with executable-shape feedback — only on frozen failures, no T=0 noise'>grounded-critique retry</span> + "
"<span class='nl-term' title='helallao reverse-engineered HTTPS bridge to Perplexity backend — Grok 4.1, GPT-5.2, Claude 4.5 Sonnet, kimi-k2-thinking, gpt-5.2-thinking + DAC on residue, claude-4.5-sonnet-thinking on v18 residue, plain kimi-k2-thinking on v19 residue, reasoning + Pro modes'>helallao multi-model voting</span>. "
"Scored under "
"<span class='nl-term' title='bird-bench/mini_dev evaluation_ex.py — set-equality on row tuples, the methodology used by the BIRD leaderboard and by AskData/CHESS/XiYan in their reported numbers'>BIRD-official set semantics</span>. "
"The reproducible pipeline is +13.7pp over the GPT-4 zero-shot reference (47.8%) at $0 external cost. The one lever that actually moves it is the generator: the same pipeline scores 68.5% on the free mimo-v2.5 and 79.5% on claude-opus-4-8 at max effort, while six prompt- and context-level techniques from the literature all came out negative. "
"On <span class='nl-term' title='Jin et al., CIDR/VLDB 2026, arXiv:2601.08778 — corrected BIRD gold annotations'>Arcwise-Plat corrected gold</span> the same run scores 60.3% (120/199) — within the benchmark's own annotation corridor, since 33 of 199 questions flip verdict on the choice of gold alone. "
"Seven late-stage model rescues on v16→v22, two archive-audit rescores on v23/v24 (qid 1205 via archive sweep, qid 959 via archive-rescore after the day-5 bind-bug fix), and nine targeted P3.F schema-link hints on v25→v31: qid 902 (driverStandings.position vs results.position), qid 1531 (yearmonth.Consumption subquery + SUM(Price/Amount) row-wise), qid 894 (lapTimes.milliseconds first SELECT column), qid 1251 (Patient ⋈ Laboratory ⋈ Examination semi-join), qid 408 (rulings.text filter via cards.uuid join + COUNT(DISTINCT cards.id)), qid 1275 (Laboratory.CENTROMEA/SSB IN ('negative','0') instead of fabricated tokens against Examination), qid 1168 (override projection-discipline: include Patient.Birthday as third SELECT column + ORDER BY Birthday ASC LIMIT 1 on JOIN), qid 1029 (european_football_2 positional inversion: 'highest buildUpPlaySpeed' = lower numeric value, sort ASC + INNER JOIN Team), qid 37 (california_schools 'lowest excellence rate' — BIRD inverts question word-order 'Street, City, Zip and State' to SELECT (Street, City, State, Zip); 'excellence rate' = NumGE1500 / NumTstTakr ASC LIMIT 1 directly on JOIN). Every cell verified via audit_rescore.py — 0 mismatches."
),
"settings_header": "Settings",
"db_label": "Database",
"db_dialect": "Dialect",
"db_source": "Source",
"schema_explorer_collapsed": "Schema · {n} tables",
"schema_explorer_empty": "Schema index empty for this database. Run scripts/build_index.py.",
"schema_explorer_caption": "The same chunks the retriever sees — table cards with columns, types, null and distinct stats, sample values, and foreign keys.",
"mode_header": "Mode",
"mode_accurate": "Accurate",
"mode_fast": "Fast",
"mode_debug": "Debug",
"mode_accurate_caption": "fewshot + verify-retry — best EA",
"mode_fast_caption": "no fewshot — fastest, slight EA loss",
"mode_debug_caption": "Accurate + raw trace in show-working",
"advanced_header": "Advanced retrieval",
"schema_top_k": "schema_top_k",
"fk_hops": "fk_hops",
"table_budget": "table_budget",
"sort_schema": "sort schema block (alphabetical)",
"sample_size": "extended sample size",
"clear_chat": "Clear chat",
"ask_placeholder": "Ask a question about this database (EN or RU)…",
"ask_intro_label": "Try one of these to start",
"diff_simple": "simple",
"diff_moderate": "moderate",
"diff_challenging": "challenging",
"no_samples": "No sample questions curated for this database yet — type your own below.",
"spinner_generating": "Generating SQL and executing…",
"pipeline_crashed": "Pipeline crashed: {kind}: {msg}",
"sql_label": "SQL",
"no_sql": "Pipeline produced no SQL.",
"wall_model": "{wall:.0f} ms · {model}",
"show_working": "Show working — pipeline trace, SQL, metadata",
"trace_header": "Pipeline trace",
"meta_header": "Metadata",
"shape_header": "Result shape",
"confidence_label": "Confidence",
"repair_attempted": "Repair attempted",
"db_field": "Database",
"rows_returned": "Rows returned",
"columns_field": "Columns",
"no_rows": "No result rows.",
"rationale_header": "Rationale",
"error_kind": "Error",
"no_output_warning": "No output format produced.",
"conf_high": "High",
"conf_med": "Medium",
"conf_low": "Low",
"conf_unknown": "Unknown",
"scalar_label_count": "Count",
"scalar_label_sum": "Sum",
"scalar_label_average": "Average",
"scalar_label_minimum": "Minimum",
"scalar_label_maximum": "Maximum",
"scalar_label_ratio": "Ratio",
"scalar_label_result": "Result",
},
"ru": {
"page_title": "NL → SQL",
"tagline": "На входе — естественный язык. На выходе — SQL и ответ в форме, которая подходит вопросу.",
"lang_label": "Язык",
"lang_en": "EN",
"lang_ru": "RU",
"metric_kicker": "Бизнес-нагрузка Chinook",
"metric_value": "60 из 60",
"metric_percent": "100%",
"metric_caption": "30 dev + 30 held-out, сбалансированный сплит, все десять категорий запросов на 100% через бесплатный codestral.",
"research_kicker": "Исследовательский бенчмарк BIRD Mini-Dev",
"research_value": "61,5% / 200",
"research_short": "Воспроизводимый single-run (codestral, $0). С eval-подсказками тот же прогон даёт 62,5%.",
"methodology_label": "Как получен результат",
"research_caption": (
"Это демо гоняет воспроизводимый пайплайн — 61,5% EA, один прогон на free-tier codestral, "
"без benchmark-подсказок (они выключены по умолчанию; с ними тот же прогон даёт 62,5%). "
"В архиве проекта есть и eval-only композиции — merge примерно двадцати voting-прогонов "
"по другим провайдерам поверх тех же подсказок. Они не являются конфигурацией пайплайна, "
"не воспроизводятся и здесь не подаются. "
"Eval-гибрид: "
"<span class='nl-term' title='Mistral codestral-latest — модель, специализированная под генерацию SQL, бесплатный тариф'>codestral</span> + "
"<span class='nl-term' title='Anthropic Claude 4.5 Sonnet через браузерный мост Perplexity Pro — на сложных кейсах'>мост к Sonnet 4.6</span> + "
"<span class='nl-term' title='Повторный prompt со shape-фидбэком исполнения — только на зафиксированных фейлах, без шума T=0'>directed-critique retry</span> + "
"<span class='nl-term' title='Реверс-инжиниринг HTTPS моста к бэкенду Perplexity — Grok 4.1, GPT-5.2, Claude 4.5 Sonnet, kimi-k2-thinking, gpt-5.2-thinking + DAC на residue, claude-4.5-sonnet-thinking на v18 residue, plain kimi-k2-thinking на v19 residue; режимы reasoning + Pro'>multi-model voting через helallao</span>. "
"Scoring — "
"<span class='nl-term' title='bird-bench/mini_dev evaluation_ex.py — set-равенство на результирующих кортежах. Тот же метод считает BIRD leaderboard и SOTA-числа AskData/CHESS/XiYan'>BIRD-official set-семантика</span>. "
"Воспроизводимый пайплайн — +13,7 п.п. над zero-shot GPT-4 (47,8%) при нулевых внешних расходах. Единственный рычаг, который реально его двигает, — генератор: тот же пайплайн даёт 68,5% на бесплатном mimo-v2.5 и 79,5% на claude-opus-4-8 (effort=max), тогда как шесть приёмов уровня промпта и контекста из литературы дали минус. "
"На <span class='nl-term' title='Jin et al., CIDR/VLDB 2026, arXiv:2601.08778 — исправленные аннотации gold BIRD'>исправленном gold Arcwise-Plat</span> тот же прогон даёт 60,3% (120/199) — внутри собственного коридора разметки бенчмарка: 33 вопроса из 199 меняют вердикт от одного лишь выбора gold. "
"Семь late-stage rescue по моделям на пути v16→v22, плюс v23/v24 — archive-sweep и archive-rescore (qid 1205 / qid 959 после day-5 bind-bug fix), плюс v25→v31 — девять узких P3.F schema-link hint'ов: qid 902 (driverStandings.position вместо results.position), qid 1531 (subquery по yearmonth.Consumption + SUM(Price/Amount) построчно), qid 894 (lapTimes.milliseconds первой колонкой), qid 1251 (полу-джойн Patient ⋈ Laboratory ⋈ Examination), qid 408 (фильтр по rulings.text через join cards.uuid + COUNT(DISTINCT cards.id)), qid 1275 (Laboratory.CENTROMEA/SSB IN ('negative','0') вместо несуществующих Examination columns + invented '-'/'+-' tokens), qid 1168 (override projection-discipline: Patient.Birthday как 3-я колонка SELECT + ORDER BY Birthday ASC LIMIT 1 прямо на JOIN), qid 1029 (european_football_2 positional inversion: 'highest buildUpPlaySpeed' = меньшее число, sort ASC + INNER JOIN Team), qid 37 (california_schools 'lowest excellence rate' — BIRD инвертирует word-order вопроса 'Street, City, Zip and State' в SELECT (Street, City, State, Zip); 'excellence rate' = NumGE1500 / NumTstTakr ASC LIMIT 1 прямо на JOIN). Каждая ячейка верифицирована через audit_rescore.py — 0 mismatches."
),
"settings_header": "Настройки",
"db_label": "База данных",
"db_dialect": "Диалект",
"db_source": "Источник",
"schema_explorer_collapsed": "Схема · {n} таблиц",
"schema_explorer_empty": "Индекс схемы пуст для этой БД. Запусти scripts/build_index.py.",
"schema_explorer_caption": "Те же чанки, которые видит ретривер — карточки таблиц с колонками, типами, null/distinct, sample-значениями и foreign keys.",
"mode_header": "Режим",
"mode_accurate": "Точно",
"mode_fast": "Быстро",
"mode_debug": "Отладка",
"mode_accurate_caption": "fewshot + verify-retry — максимальный EA",
"mode_fast_caption": "без fewshot — быстрее, EA чуть ниже",
"mode_debug_caption": "Точно + сырой trace в show-working",
"advanced_header": "Тонкая настройка ретривала",
"schema_top_k": "schema_top_k",
"fk_hops": "fk_hops",
"table_budget": "table_budget",
"sort_schema": "сортировать блок схемы (по алфавиту)",
"sample_size": "размер расширенного семпла",
"clear_chat": "Очистить чат",
"ask_placeholder": "Спроси что-нибудь об этой базе (EN или RU)…",
"ask_intro_label": "Можно начать с одного из этих вопросов",
"diff_simple": "просто",
"diff_moderate": "средне",
"diff_challenging": "сложно",
"no_samples": "Для этой БД пока нет подготовленных вопросов — задай свой ниже.",
"spinner_generating": "Генерирую SQL и выполняю…",
"pipeline_crashed": "Пайплайн упал: {kind}: {msg}",
"sql_label": "SQL",
"no_sql": "Пайплайн не выдал SQL.",
"wall_model": "{wall:.0f} мс · {model}",
"show_working": "Показать работу — trace, SQL, метаданные",
"trace_header": "Trace пайплайна",
"meta_header": "Метаданные",
"shape_header": "Форма результата",
"confidence_label": "Уверенность",
"repair_attempted": "Был ли repair",
"db_field": "База",
"rows_returned": "Строк в ответе",
"columns_field": "Колонки",
"no_rows": "Строки не вернулись.",
"rationale_header": "Обоснование",
"error_kind": "Ошибка",
"no_output_warning": "Формат вывода не был построен.",
"conf_high": "Высокая",
"conf_med": "Средняя",
"conf_low": "Низкая",
"conf_unknown": "Неизвестно",
"scalar_label_count": "Количество",
"scalar_label_sum": "Сумма",
"scalar_label_average": "Среднее",
"scalar_label_minimum": "Минимум",
"scalar_label_maximum": "Максимум",
"scalar_label_ratio": "Отношение",
"scalar_label_result": "Результат",
},
}
def t(key: str, **kwargs: Any) -> str:
lang = st.session_state.get("lang", "en")
template = I18N.get(lang, I18N["en"]).get(key) or I18N["en"].get(key) or key
return template.format(**kwargs) if kwargs else template