// token 数在界面上以 K(千)为单位输入与显示;存储与 API 仍是原始 token 数,只在前端换算。 // 1K = 1000 token(模型目录的上下文窗口也是按 1000 计,如 128K = 128000)。 export const TOKENS_PER_K = 1000; /** 去掉小数末尾的 0:1.50 → "1.5",2.00 → "2" */ const trim = (n: number, digits: number) => String(Number(n.toFixed(digits))); /** 列表 / 详情里的 token 数:<1000 原样,千级 "128K",百万级 "1.5M" */ export function formatTokens(n: number | null | undefined): string { if (n === null || n === undefined || !Number.isFinite(n)) return "—"; const abs = Math.abs(n); if (abs < TOKENS_PER_K) return String(Math.round(n)); if (abs < 1_000_000) { const k = n / TOKENS_PER_K; // 999.95K 以上四舍五入会变成 1000K,直接进位到 M if (Math.abs(Number(k.toFixed(1))) < 1000) return `${trim(k, Math.abs(k) < 10 ? 2 : 1)}K`; } return `${trim(n / 1_000_000, 2)}M`; } /** 原始 token 数 → 输入框里的 K 值字符串(null → 空串);最多 3 位小数,正好换回原值 */ export function tokensToK(n: number | null | undefined): string { if (n === null || n === undefined || !Number.isFinite(n)) return ""; return trim(n / TOKENS_PER_K, 3); } /** * 输入框里的 K 值 → 原始 token 数。 * 空串 → undefined;不是数字 → NaN(交给校验报错);其余四舍五入到整数 token。 */ export function kToTokens(input: string): number | undefined { const s = input.trim().replace(/[kK]$/, "").trim(); if (s === "") return undefined; if (!/^\d+(\.\d+)?$|^\.\d+$/.test(s)) return Number.NaN; return Math.round(Number(s) * TOKENS_PER_K); } export type TokenRange = { min?: number; max?: number; required?: boolean }; /** 范围说明:{min:4000,max:2000000} → "4K–2000K" */ export function tokenRangeText(r: TokenRange): string | null { if (r.min !== undefined && r.max !== undefined) return `${tokensToK(r.min)}K–${tokensToK(r.max)}K`; if (r.min !== undefined) return `${tokensToK(r.min)}K 以上`; if (r.max !== undefined) return `不超过 ${tokensToK(r.max)}K`; return null; } /** 校验 K 值输入;通过返回 null,否则返回一句错误 */ export function tokenInputError(input: string, r: TokenRange = {}): string | null { const t = kToTokens(input); if (t === undefined) return r.required ? "填一个数,单位 K" : null; const range = tokenRangeText(r); if (Number.isNaN(t)) return "只填数字,单位 K,如 128 或 1.5"; if (t <= 0 || (r.min !== undefined && t < r.min) || (r.max !== undefined && t > r.max)) return range ? `填 ${range}` : "填大于 0 的数"; return null; }