Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3575bf7e60 |
@@ -3,6 +3,16 @@
|
|||||||
All notable changes to this project are documented here.
|
All notable changes to this project are documented here.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
||||||
|
|
||||||
|
## [0.2.31] - 2026-07-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Structured O(1) Nyström Attention & Reasoning Control**: Enhanced settings drawer with structured parameter sections for O(1) Nyström Streaming Attention (`o1_m`, `o1_window`, `o1_sink`), Generation (Temp, Top-P, MaxTokens, System Prompt), Reasoning ("Disable reasoning" toggle mapping to `think_budget = 0` for Qwen3/3.5 models), and Runtime (`skip_mtp` via `CMF_MTP=0`).
|
||||||
|
- **Persistent Admin Token Configuration**: Support for explicit `token` field in `config/gateway.toml` under `[admin]` block to prevent authorization invalidation across restarts.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **JavaScript UI Helper Restoration**: Restored `opt(...)` helper in `web/js/ui.js` and `web/js/views/import.js` to ensure HF model import modal options render smoothly.
|
||||||
|
- **Engine Command Flag Accuracy**: Fixed `CMF_MTP=0` environment flag pass-through for `cortiq serve` processes.
|
||||||
|
|
||||||
## [0.2.30] - 2026-07-22
|
## [0.2.30] - 2026-07-22
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cortiq-gateway"
|
name = "cortiq-gateway"
|
||||||
version = "0.2.30"
|
version = "0.2.31"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.75"
|
rust-version = "1.75"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -1336,6 +1336,9 @@ async fn register_import(State(state): State<SharedState>, Path(job): Path<Strin
|
|||||||
think_budget: None,
|
think_budget: None,
|
||||||
system_prompt: None,
|
system_prompt: None,
|
||||||
o1: None,
|
o1: None,
|
||||||
|
o1_m: None,
|
||||||
|
o1_window: None,
|
||||||
|
o1_sink: None,
|
||||||
skip_mtp: false,
|
skip_mtp: false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+17
-3
@@ -293,13 +293,27 @@ fn spawn_serve(server: &CmfServer, cfg: &CmfCfg) -> Result<Child, String> {
|
|||||||
if server.gpu {
|
if server.gpu {
|
||||||
cmd.env("CMF_GPU", "1");
|
cmd.env("CMF_GPU", "1");
|
||||||
}
|
}
|
||||||
|
// O(1) Nyström attention: layers spec + sub-parameters.
|
||||||
if let Some(o1) = &server.o1 {
|
if let Some(o1) = &server.o1 {
|
||||||
if !o1.trim().is_empty() && o1 != "off" {
|
let s = o1.trim();
|
||||||
cmd.arg("--o1").arg(o1);
|
if !s.is_empty() {
|
||||||
|
// Pass even "off" so it explicitly overrides a file converter hint.
|
||||||
|
cmd.arg("--o1").arg(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(m) = server.o1_m {
|
||||||
|
cmd.arg("--o1-m").arg(m.to_string());
|
||||||
|
}
|
||||||
|
if let Some(w) = server.o1_window {
|
||||||
|
cmd.arg("--o1-window").arg(w.to_string());
|
||||||
|
}
|
||||||
|
if let Some(sink) = server.o1_sink {
|
||||||
|
cmd.arg("--o1-sink").arg(sink.to_string());
|
||||||
|
}
|
||||||
|
// MTP (Multi-Token Prediction) speculative decoding: the engine reads
|
||||||
|
// CMF_MTP env; "0" disables. There is no CLI flag for this.
|
||||||
if server.skip_mtp {
|
if server.skip_mtp {
|
||||||
cmd.arg("--skip-mtp");
|
cmd.env("CMF_MTP", "0");
|
||||||
}
|
}
|
||||||
cmd.stdout(Stdio::null())
|
cmd.stdout(Stdio::null())
|
||||||
.stderr(Stdio::null())
|
.stderr(Stdio::null())
|
||||||
|
|||||||
+19
-4
@@ -98,10 +98,19 @@ pub struct CmfServer {
|
|||||||
/// Default system prompt prepended if request lacks one.
|
/// Default system prompt prepended if request lacks one.
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub system_prompt: Option<String>,
|
pub system_prompt: Option<String>,
|
||||||
/// O(1) constant-memory streaming attention hint (all, deep, custom, off).
|
/// O(1) Nyström attention layer spec (all | deepN | i,j,k | off).
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub o1: Option<String>,
|
pub o1: Option<String>,
|
||||||
/// Skip Multi-Token Prediction (MTP) heads.
|
/// O(1) landmark budget (default 32; ≥4).
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub o1_m: Option<u32>,
|
||||||
|
/// O(1) exact-window width (default 128).
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub o1_window: Option<u32>,
|
||||||
|
/// O(1) permanent exact sink keys (default 4, StreamingLLM discipline).
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub o1_sink: Option<u32>,
|
||||||
|
/// Disable Multi-Token Prediction speculative decoding (CMF_MTP=0).
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub skip_mtp: bool,
|
pub skip_mtp: bool,
|
||||||
}
|
}
|
||||||
@@ -199,6 +208,9 @@ impl CmfCfg {
|
|||||||
think_budget: None,
|
think_budget: None,
|
||||||
system_prompt: None,
|
system_prompt: None,
|
||||||
o1: None,
|
o1: None,
|
||||||
|
o1_m: None,
|
||||||
|
o1_window: None,
|
||||||
|
o1_sink: None,
|
||||||
skip_mtp: false,
|
skip_mtp: false,
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@@ -510,10 +522,12 @@ pub struct AdminCfg {
|
|||||||
/// Whether the admin panel and admin API (`/admin`, `/admin/api/*`) are enabled.
|
/// Whether the admin panel and admin API (`/admin`, `/admin/api/*`) are enabled.
|
||||||
#[serde(default = "default_admin_enabled")]
|
#[serde(default = "default_admin_enabled")]
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
/// Name of the env variable holding the admin token. If unset (or empty),
|
/// Name of the env variable holding the admin token.
|
||||||
/// a token is generated at startup and printed to the log.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub token_env: Option<String>,
|
pub token_env: Option<String>,
|
||||||
|
/// Persistent admin token configured directly in toml.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub token: Option<String>,
|
||||||
/// Optional separate bind address for the admin surface (e.g. `127.0.0.1:9001`).
|
/// Optional separate bind address for the admin surface (e.g. `127.0.0.1:9001`).
|
||||||
/// If unset, the admin interface lives on the main `listen` address under `/admin`.
|
/// If unset, the admin interface lives on the main `listen` address under `/admin`.
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
@@ -524,6 +538,7 @@ impl Default for AdminCfg {
|
|||||||
Self {
|
Self {
|
||||||
enabled: default_admin_enabled(),
|
enabled: default_admin_enabled(),
|
||||||
token_env: None,
|
token_env: None,
|
||||||
|
token: None,
|
||||||
listen: None,
|
listen: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ fn resolve_admin_token(cfg: &Config, args: &Args) -> (String, bool) {
|
|||||||
return (t.clone(), false);
|
return (t.clone(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(t) = &cfg.admin.token {
|
||||||
|
if !t.is_empty() {
|
||||||
|
return (t.clone(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
(admin::random_token(24), true)
|
(admin::random_token(24), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+4
@@ -23,6 +23,10 @@ export function clear(node) {
|
|||||||
while (node && node.firstChild) node.removeChild(node.firstChild);
|
while (node && node.firstChild) node.removeChild(node.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function opt(v, label, sel) {
|
||||||
|
return h("option", { value: v, selected: sel ? true : null }, label || v);
|
||||||
|
}
|
||||||
|
|
||||||
export function mount(node, ...children) {
|
export function mount(node, ...children) {
|
||||||
clear(node);
|
clear(node);
|
||||||
for (const c of children.flat())
|
for (const c of children.flat())
|
||||||
|
|||||||
Vendored
+1
-4
@@ -2,7 +2,7 @@
|
|||||||
// live progress view. Search HF, pick quantization + advanced params, watch
|
// live progress view. Search HF, pick quantization + advanced params, watch
|
||||||
// the conversion (multiple in parallel, resumable across tab switches), then
|
// the conversion (multiple in parallel, resumable across tab switches), then
|
||||||
// register the result as a local model.
|
// register the result as a local model.
|
||||||
import { h, mount, toast } from "../ui.js";
|
import { h, mount, toast, opt } from "../ui.js";
|
||||||
import { t } from "../i18n.js";
|
import { t } from "../i18n.js";
|
||||||
import { api } from "../api.js";
|
import { api } from "../api.js";
|
||||||
|
|
||||||
@@ -31,9 +31,6 @@ function field(label, control, hint) {
|
|||||||
return h("label", { class: "field" }, h("span", {}, label), control,
|
return h("label", { class: "field" }, h("span", {}, label), control,
|
||||||
hint ? h("div", { class: "hint" }, hint) : null);
|
hint ? h("div", { class: "hint" }, hint) : null);
|
||||||
}
|
}
|
||||||
function opt(v, label, sel) {
|
|
||||||
return h("option", { value: v, selected: sel ? true : null }, label || v);
|
|
||||||
}
|
|
||||||
function fmtNum(n) {
|
function fmtNum(n) {
|
||||||
if (n == null) return "—";
|
if (n == null) return "—";
|
||||||
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
||||||
|
|||||||
Vendored
+4
-7
@@ -7,9 +7,6 @@ import { appState } from "../app.js";
|
|||||||
function field(label, control, hint) {
|
function field(label, control, hint) {
|
||||||
return h("label", { class: "field" }, h("span", {}, label), control, hint ? h("div", { class: "hint" }, hint) : null);
|
return h("label", { class: "field" }, h("span", {}, label), control, hint ? h("div", { class: "hint" }, hint) : null);
|
||||||
}
|
}
|
||||||
function opt(v, label, sel) {
|
|
||||||
return h("option", { value: v, selected: sel ? true : null }, label || v);
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyBadge(src) {
|
function keyBadge(src) {
|
||||||
const map = { store: "store", env: "env", missing: "bad", none: "" };
|
const map = { store: "store", env: "env", missing: "bad", none: "" };
|
||||||
@@ -124,10 +121,10 @@ function modelForm(meta, existing) {
|
|||||||
const maxTokIn = h("input", { type: "number", min: "1", placeholder: "2048", value: m.max_tokens ?? "" });
|
const maxTokIn = h("input", { type: "number", min: "1", placeholder: "2048", value: m.max_tokens ?? "" });
|
||||||
const thinkIn = h("input", { type: "number", min: "0", placeholder: "1024", value: m.think_budget ?? "" });
|
const thinkIn = h("input", { type: "number", min: "0", placeholder: "1024", value: m.think_budget ?? "" });
|
||||||
const o1Sel = h("select", {},
|
const o1Sel = h("select", {},
|
||||||
opt("", t("import.adv.auto")),
|
h("option", { value: "" }, t("import.adv.auto")),
|
||||||
opt("all", "all — O(1) Attention"),
|
h("option", { value: "all" }, "all — O(1) Attention"),
|
||||||
opt("deep", "deep — O(1) Deep"),
|
h("option", { value: "deep" }, "deep — O(1) Deep"),
|
||||||
opt("off", "off — Standard"));
|
h("option", { value: "off" }, "off — Standard"));
|
||||||
if (m.o1) o1Sel.value = m.o1;
|
if (m.o1) o1Sel.value = m.o1;
|
||||||
const skipMtpCb = h("input", { type: "checkbox", checked: m.skip_mtp ? true : null });
|
const skipMtpCb = h("input", { type: "checkbox", checked: m.skip_mtp ? true : null });
|
||||||
const sysPromptIn = h("textarea", { rows: 2, placeholder: t("models.form.systemPromptPlaceholder"), value: m.system_prompt || "" });
|
const sysPromptIn = h("textarea", { rows: 2, placeholder: t("models.form.systemPromptPlaceholder"), value: m.system_prompt || "" });
|
||||||
|
|||||||
Vendored
+74
-22
@@ -253,33 +253,82 @@ export async function renderSettings() {
|
|||||||
} catch (e) { mount(st, String(e.message || e)); }
|
} catch (e) { mount(st, String(e.message || e)); }
|
||||||
checkBtn.disabled = false;
|
checkBtn.disabled = false;
|
||||||
});
|
});
|
||||||
// ⚙ Model Generation & Thinking Parameters drawer
|
|
||||||
const tempIn = h("input", { type: "number", step: "0.05", min: "0", max: "2.0", placeholder: "0.7", value: sv.temperature ?? "", style: "width:65px" });
|
|
||||||
const topPIn = h("input", { type: "number", step: "0.05", min: "0", max: "1.0", placeholder: "0.9", value: sv.top_p ?? "", style: "width:65px" });
|
|
||||||
const maxTokIn = h("input", { type: "number", min: "1", placeholder: "2048", value: sv.max_tokens ?? "", style: "width:80px" });
|
|
||||||
const thinkIn = h("input", { type: "number", min: "0", placeholder: "1024", value: sv.think_budget ?? "", style: "width:80px" });
|
|
||||||
const o1Sel = h("select", { style: "width:110px" },
|
|
||||||
opt("", "O(1) auto"),
|
|
||||||
opt("all", "O(1) all"),
|
|
||||||
opt("deep", "O(1) deep"),
|
|
||||||
opt("off", "O(1) off"));
|
|
||||||
if (sv.o1) o1Sel.value = sv.o1;
|
|
||||||
const skipMtpCb = h("input", { type: "checkbox", checked: sv.skip_mtp ? true : null });
|
|
||||||
const sysIn = h("input", { placeholder: t("models.form.systemPromptPlaceholder"), value: sv.system_prompt || "", style: "flex:1" });
|
|
||||||
|
|
||||||
const drawer = h("div", { class: "flex wrap gap-sm", style: "display:none;width:100%;margin-top:4px;padding:6px;background:var(--bg-subtle);border-radius:4px;align-items:center" },
|
// ── O(1) Nyström Attention ──
|
||||||
|
// NOT a "reasoning mode". This is a memory-efficient streaming attention
|
||||||
|
// kernel (Nyström/landmark) that replaces standard KV-cache attention,
|
||||||
|
// giving O(1) memory per decode step instead of O(n).
|
||||||
|
const o1Sel = h("select", { style: "width:120px", title: "O(1) Nyström attention layer spec: which layers replace KV-cache with streaming Nyström attention" },
|
||||||
|
h("option", { value: "" }, "O(1) авто"),
|
||||||
|
h("option", { value: "all" }, "O(1) все слои"),
|
||||||
|
h("option", { value: "deep" }, "O(1) глубокие"),
|
||||||
|
h("option", { value: "off" }, "O(1) выкл."));
|
||||||
|
if (sv.o1) o1Sel.value = sv.o1;
|
||||||
|
const o1mIn = h("input", { type: "number", min: "4", placeholder: "32", value: sv.o1_m ?? "", style: "width:55px", title: "Landmark budget (≥4, default 32). More landmarks ≠ better: m=64 measured worse." });
|
||||||
|
const o1wIn = h("input", { type: "number", min: "1", placeholder: "128", value: sv.o1_window ?? "", style: "width:60px", title: "Exact-window width — main quality lever (default 128)" });
|
||||||
|
const o1sinkIn = h("input", { type: "number", min: "0", placeholder: "4", value: sv.o1_sink ?? "", style: "width:50px", title: "Permanent exact sink keys, StreamingLLM discipline (default 4)" });
|
||||||
|
|
||||||
|
// ── Generation parameters ──
|
||||||
|
const tempIn = h("input", { type: "number", step: "0.05", min: "0", max: "2.0", placeholder: "0.7", value: sv.temperature ?? "", style: "width:60px" });
|
||||||
|
const topPIn = h("input", { type: "number", step: "0.05", min: "0", max: "1.0", placeholder: "0.9", value: sv.top_p ?? "", style: "width:60px" });
|
||||||
|
const maxTokIn = h("input", { type: "number", min: "1", placeholder: "2048", value: sv.max_tokens ?? "", style: "width:75px" });
|
||||||
|
// think_budget = 0 means reasoning disabled (enable_thinking=false);
|
||||||
|
// null = model decides; N>0 = token budget for the <think> block.
|
||||||
|
const noThinkCb = h("input", { type: "checkbox", checked: (sv.think_budget === 0) ? true : null, title: "Отключить режим размышлений (think_budget=0, enable_thinking=false для Qwen3/3.5)" });
|
||||||
|
const thinkIn = h("input", { type: "number", min: "1", placeholder: "авто", value: (sv.think_budget && sv.think_budget > 0) ? sv.think_budget : "", style: "width:75px", title: "Бюджет токенов на размышления (think_budget). Пустое = модель решает сама." });
|
||||||
|
if (sv.think_budget === 0) thinkIn.disabled = true;
|
||||||
|
noThinkCb.addEventListener("change", () => {
|
||||||
|
thinkIn.disabled = noThinkCb.checked;
|
||||||
|
if (noThinkCb.checked) thinkIn.value = "";
|
||||||
|
});
|
||||||
|
const sysIn = h("input", { placeholder: "System prompt (optional)", value: sv.system_prompt || "", style: "flex:1;min-width:200px" });
|
||||||
|
|
||||||
|
// ── MTP (Multi-Token Prediction): speculative decoding, NOT reasoning ──
|
||||||
|
const skipMtpCb = h("input", { type: "checkbox", checked: sv.skip_mtp ? true : null, title: "Disable MTP speculative decoding (env CMF_MTP=0)" });
|
||||||
|
|
||||||
|
// ── Settings drawer ──
|
||||||
|
const drawerStyle = "display:none;width:100%;margin-top:6px;padding:10px 12px;background:var(--bg-subtle);border-radius:6px;border:1px solid var(--border)";
|
||||||
|
const groupStyle = "display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:4px 0";
|
||||||
|
const labelStyle = "font-size:11px;color:var(--text-muted);font-weight:600;text-transform:uppercase;letter-spacing:0.5px;width:100%;margin-bottom:2px";
|
||||||
|
|
||||||
|
const drawer = h("div", { style: drawerStyle },
|
||||||
|
// Group 1: O(1) Nyström Attention
|
||||||
|
h("div", { style: labelStyle }, "O(1) Nyström Attention"),
|
||||||
|
h("div", { style: groupStyle },
|
||||||
|
h("span", { class: "small muted" }, "Слои:"), o1Sel,
|
||||||
|
h("span", { class: "small muted" }, "m:"), o1mIn,
|
||||||
|
h("span", { class: "small muted" }, "Window:"), o1wIn,
|
||||||
|
h("span", { class: "small muted" }, "Sink:"), o1sinkIn
|
||||||
|
),
|
||||||
|
h("hr", { style: "border:none;border-top:1px solid var(--border);margin:6px 0" }),
|
||||||
|
// Group 2: Generation
|
||||||
|
h("div", { style: labelStyle }, "Генерация"),
|
||||||
|
h("div", { style: groupStyle },
|
||||||
h("span", { class: "small muted" }, "Temp:"), tempIn,
|
h("span", { class: "small muted" }, "Temp:"), tempIn,
|
||||||
h("span", { class: "small muted" }, "Top-P:"), topPIn,
|
h("span", { class: "small muted" }, "Top-P:"), topPIn,
|
||||||
h("span", { class: "small muted" }, "MaxTokens:"), maxTokIn,
|
h("span", { class: "small muted" }, "Max токенов:"), maxTokIn
|
||||||
h("span", { class: "small muted" }, "ThinkBudget:"), thinkIn,
|
),
|
||||||
o1Sel,
|
h("div", { style: groupStyle },
|
||||||
h("label", { class: "check small" }, skipMtpCb, "Skip MTP"),
|
h("span", { class: "small muted" }, "System prompt:"), sysIn
|
||||||
h("span", { class: "small muted" }, "System:"), sysIn
|
),
|
||||||
|
h("hr", { style: "border:none;border-top:1px solid var(--border);margin:6px 0" }),
|
||||||
|
// Group 3: Reasoning (thinking)
|
||||||
|
h("div", { style: labelStyle }, "Режим размышлений"),
|
||||||
|
h("div", { style: groupStyle },
|
||||||
|
h("label", { class: "check small", title: "Для моделей Qwen3/3.5: enable_thinking=false — модель отвечает напрямую без блока <think>" }, noThinkCb, "Отключить размышления"),
|
||||||
|
h("span", { class: "small muted" }, "Think budget:"), thinkIn
|
||||||
|
),
|
||||||
|
h("hr", { style: "border:none;border-top:1px solid var(--border);margin:6px 0" }),
|
||||||
|
// Group 4: Runtime
|
||||||
|
h("div", { style: labelStyle }, "Runtime"),
|
||||||
|
h("div", { style: groupStyle },
|
||||||
|
h("label", { class: "check small", title: "MTP — Multi-Token Prediction (спекулятивное декодирование). Отключение замедляет генерацию, но стабилизирует output." }, skipMtpCb, "Отключить MTP")
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const gearBtn = h("button", { class: "btn small", type: "button", title: "⚙ " + t("models.form.paramsTitle") }, "⚙");
|
const gearBtn = h("button", { class: "btn small", type: "button", title: "⚙ Настройки модели" }, "⚙");
|
||||||
gearBtn.addEventListener("click", () => {
|
gearBtn.addEventListener("click", () => {
|
||||||
drawer.style.display = drawer.style.display === "none" ? "flex" : "none";
|
drawer.style.display = drawer.style.display === "none" ? "block" : "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
const row = h("div", { class: "flex wrap", style: "gap:6px;align-items:center;margin:6px 0" },
|
const row = h("div", { class: "flex wrap", style: "gap:6px;align-items:center;margin:6px 0" },
|
||||||
@@ -293,8 +342,11 @@ export async function renderSettings() {
|
|||||||
temperature: tempIn.value !== "" ? parseFloat(tempIn.value) : null,
|
temperature: tempIn.value !== "" ? parseFloat(tempIn.value) : null,
|
||||||
top_p: topPIn.value !== "" ? parseFloat(topPIn.value) : null,
|
top_p: topPIn.value !== "" ? parseFloat(topPIn.value) : null,
|
||||||
max_tokens: maxTokIn.value !== "" ? parseInt(maxTokIn.value) : null,
|
max_tokens: maxTokIn.value !== "" ? parseInt(maxTokIn.value) : null,
|
||||||
think_budget: thinkIn.value !== "" ? parseInt(thinkIn.value) : null,
|
think_budget: noThinkCb.checked ? 0 : (thinkIn.value !== "" ? parseInt(thinkIn.value) : null),
|
||||||
o1: o1Sel.value || null,
|
o1: o1Sel.value || null,
|
||||||
|
o1_m: o1mIn.value !== "" ? parseInt(o1mIn.value) : null,
|
||||||
|
o1_window: o1wIn.value !== "" ? parseInt(o1wIn.value) : null,
|
||||||
|
o1_sink: o1sinkIn.value !== "" ? parseInt(o1sinkIn.value) : null,
|
||||||
skip_mtp: skipMtpCb.checked,
|
skip_mtp: skipMtpCb.checked,
|
||||||
system_prompt: sysIn.value.trim() || null,
|
system_prompt: sysIn.value.trim() || null,
|
||||||
}) };
|
}) };
|
||||||
|
|||||||
Reference in New Issue
Block a user