From d93ac537c89ae55e86947a4a8e0b25b70d42955a Mon Sep 17 00:00:00 2001 From: infosave2007 Date: Tue, 14 Jul 2026 11:19:00 +0300 Subject: [PATCH] docs(import): human-readable labels + hover help for the O(1) knobs Landmarks / Exact window / Sink keys now carry a '?' tooltip explaining in plain language what each knob does, its trade-off, and the validated default (32 / 128 / 4), in EN + RU. --- Cargo.lock | 2 +- Cargo.toml | 2 +- web/js/i18n/en.js | 6 ++++++ web/js/i18n/ru.js | 6 ++++++ web/js/views/import.js | 16 +++++++++++----- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3cde71..2c326f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -285,7 +285,7 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "cortiq-gateway" -version = "0.2.17" +version = "0.2.18" dependencies = [ "anyhow", "arc-swap", diff --git a/Cargo.toml b/Cargo.toml index 05f4d42..e72356d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cortiq-gateway" -version = "0.2.17" +version = "0.2.18" edition = "2021" rust-version = "1.75" license = "Apache-2.0" diff --git a/web/js/i18n/en.js b/web/js/i18n/en.js index 4b8bc22..0948473 100644 --- a/web/js/i18n/en.js +++ b/web/js/i18n/en.js @@ -412,6 +412,12 @@ export default { "import.adv.o1DeepN": "N deep layers", "import.adv.o1Layers": "Layers (comma-separated)", "import.adv.o1mHint": "landmark budget (default 32)", + "import.adv.o1mLabel": "Landmarks (--o1-m)", + "import.adv.o1mHelp": "How many landmark tokens summarize the whole older history when attention is approximated. More = closer to exact attention but slower and more memory; fewer = faster but rougher. 32 is the validated sweet spot — change only if you know why.", + "import.adv.o1windowLabel": "Exact window (--o1-window)", + "import.adv.o1windowHelp": "The last N tokens always get exact (non-approximated) attention. This protects quality on the text the model just wrote/read. Bigger = better local quality, more memory. Default 128.", + "import.adv.o1sinkLabel": "Sink keys (--o1-sink)", + "import.adv.o1sinkHelp": "The first N tokens of the context are kept exact forever ('attention sinks'). Models lean on these anchors — keeping them exact stabilizes long generations. Default 4; rarely needs changing.", "import.adv.o1windowHint": "exact-window width (default 128)", "import.adv.o1sinkHint": "permanent exact sink keys (default 4)", }; diff --git a/web/js/i18n/ru.js b/web/js/i18n/ru.js index b8591b1..7daf6e4 100644 --- a/web/js/i18n/ru.js +++ b/web/js/i18n/ru.js @@ -411,6 +411,12 @@ export default { "import.adv.o1DeepN": "N глубоких слоёв", "import.adv.o1Layers": "Слои (через запятую)", "import.adv.o1mHint": "число опорных точек (по умолчанию 32)", + "import.adv.o1mLabel": "Опорные точки (--o1-m)", + "import.adv.o1mHelp": "Сколько опорных токенов представляют всю старую историю при аппроксимации внимания. Больше — ближе к точному вниманию, но медленнее и больше памяти; меньше — быстрее, но грубее. 32 — проверенное значение; меняйте, только если понимаете зачем.", + "import.adv.o1windowLabel": "Точное окно (--o1-window)", + "import.adv.o1windowHelp": "Последние N токенов всегда обрабатываются точным (не аппроксимированным) вниманием — это защищает качество на только что написанном/прочитанном тексте. Больше — лучше локальное качество, больше памяти. По умолчанию 128.", + "import.adv.o1sinkLabel": "Sink-ключи (--o1-sink)", + "import.adv.o1sinkHelp": "Первые N токенов контекста навсегда остаются точными («якоря внимания»). Модели опираются на эти якоря — их точность стабилизирует длинную генерацию. По умолчанию 4; менять почти никогда не нужно.", "import.adv.o1windowHint": "ширина точного окна (по умолчанию 128)", "import.adv.o1sinkHint": "постоянные точные sink-ключи (по умолчанию 4)", }; diff --git a/web/js/views/import.js b/web/js/views/import.js index 97ebba5..26b40a9 100644 --- a/web/js/views/import.js +++ b/web/js/views/import.js @@ -15,8 +15,14 @@ const QUANTS = [ ["F32", "import.q.f32"], ]; -function field(label, control, hint) { - return h("label", { class: "field" }, h("span", {}, label), control, +// A small "?" badge with a hover/focus tooltip (same style as Settings). +function help(text) { + return text ? h("span", { class: "help", title: text, tabindex: "0", role: "img", "aria-label": text }, "?") : null; +} +function field(label, control, hint, helpText) { + return h("label", { class: "field" }, + h("span", {}, label, helpText ? " " : null, help(helpText)), + control, hint ? h("div", { class: "hint" }, hint) : null); } function opt(v, label, sel) { @@ -141,9 +147,9 @@ export function renderImport() { field(t("import.adv.o1DeepN"), o1DeepIn), field(t("import.adv.o1Layers"), o1CustomIn)); const o1Knobs = h("div", { class: "row", style: "display:none" }, - field("--o1-m", o1M, t("import.adv.o1mHint")), - field("--o1-window", o1Window, t("import.adv.o1windowHint")), - field("--o1-sink", o1Sink, t("import.adv.o1sinkHint"))); + field(t("import.adv.o1mLabel"), o1M, t("import.adv.o1mHint"), t("import.adv.o1mHelp")), + field(t("import.adv.o1windowLabel"), o1Window, t("import.adv.o1windowHint"), t("import.adv.o1windowHelp")), + field(t("import.adv.o1sinkLabel"), o1Sink, t("import.adv.o1sinkHint"), t("import.adv.o1sinkHelp"))); o1Sel.addEventListener("change", () => { const on = !!o1Sel.value; o1Knobs.style.display = on ? "" : "none";