From e15aab6d016ad701a4325027f94df6d37b7d22fa Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Thu, 9 Jul 2026 14:38:02 -0500 Subject: [PATCH] fix(changelog): use legend framework labels for updated-config entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit formatConfigKeys treated everything after the GPU segment as one framework token, so config keys with trailing descriptors (e.g. sglang-agentic-hicache) missed the FRAMEWORK_LABELS lookup and fell back to shouted caps ("SGLANG AGENTIC HICACHE"). Greedy-match the longest known framework prefix — the same mapping the chart legend uses — and title-case the leftover descriptors, so the dropdown reads "B200 (SGLang, Agentic, Hicache)". MTP/EAGLE handling now applies to any descriptor position instead of only a trailing -mtp. 中文:changelog 下拉框中"Updated Configs"此前将 GPU 之后的全部片段当作 单个框架 token,带描述符的 config key(如 sglang-agentic-hicache)无法 命中 FRAMEWORK_LABELS 映射而回退为全大写。现改为按图例使用的同一框架 映射(最长前缀匹配)解析框架名,剩余描述符首字母大写显示。 --- .../utils/changelogFormatters.test.ts | 20 ++++++++++++ .../inference/utils/changelogFormatters.tsx | 32 ++++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/packages/app/src/components/inference/utils/changelogFormatters.test.ts b/packages/app/src/components/inference/utils/changelogFormatters.test.ts index f8ceb168..b8d9ecf1 100644 --- a/packages/app/src/components/inference/utils/changelogFormatters.test.ts +++ b/packages/app/src/components/inference/utils/changelogFormatters.test.ts @@ -43,6 +43,26 @@ describe('formatConfigKeys', () => { expect(result).toContain('TRTLLM'); expect(result).toContain('FP4'); }); + + it('uses the legend framework label for keys with trailing descriptors', () => { + expect(formatConfigKeys('dsv4-fp4-b200-sglang-agentic-hicache')).toBe( + 'B200 (SGLang, Agentic, Hicache) DeepSeek-V4-Pro FP4', + ); + }); + + it('keeps multi-token frameworks intact ahead of descriptors', () => { + const result = formatConfigKeys('dsv4-fp4-gb200-llmd-vllm-agentic'); + expect(result).toContain('llm-d vLLM'); + expect(result).toContain('Agentic'); + expect(result).not.toContain('LLMD'); + }); + + it('still renders M3 mtp as EAGLE after a descriptor split', () => { + const result = formatConfigKeys('minimaxm3-fp8-h100-vllm-agentic-mtp'); + expect(result).toContain('vLLM'); + expect(result).toContain('Agentic'); + expect(result).toContain('EAGLE'); + }); }); describe('configKeyMatchesHwKey', () => { diff --git a/packages/app/src/components/inference/utils/changelogFormatters.tsx b/packages/app/src/components/inference/utils/changelogFormatters.tsx index aae20a0b..7b0f9795 100644 --- a/packages/app/src/components/inference/utils/changelogFormatters.tsx +++ b/packages/app/src/components/inference/utils/changelogFormatters.tsx @@ -1,4 +1,5 @@ import { + FRAMEWORK_LABELS, resolveFrameworkAliasesInString, resolveFrameworkPartLabel, } from '@semianalysisai/inferencex-constants'; @@ -43,13 +44,28 @@ export function formatConfigKeys(key: string) { const model = parts[0]; const precision = parts[1]; const gpu = parts[2]; - const framework = parts.slice(3).join('-'); - // Strip -mtp suffix before lookup; MTP is shown separately - const isMtp = framework.endsWith('-mtp'); - const baseFramework = isMtp ? framework.slice(0, -4) : framework; - const baseLabel = getFrameworkLabel(baseFramework); - // M3's `mtp` spec token renders as "EAGLE"; every other model keeps "MTP". - const mtpLabel = resolveFrameworkPartLabel(MODEL_PREFIX_MAPPING[model], 'mtp'); - const frameworkLabel = isMtp ? `${baseLabel}, ${mtpLabel}` : baseLabel; + // Canonicalize legacy framework substrings first (sglang-disagg → mori-sglang, …) + // so the tail matches the same FRAMEWORK_LABELS mapping the legend uses. + const tokens = resolveFrameworkAliasesInString(parts.slice(3).join('-')).split('-'); + // Config-key tails can carry extra descriptors after the framework + // (e.g. `sglang-agentic-hicache`), and frameworks themselves can be + // multi-token (`dynamo-sglang`, `llmd-vllm`). Greedy longest-prefix match + // against the known framework labels splits the two apart. + // No prefix match → treat the whole tail as the framework (legacy fallback). + let fwTokens = tokens.length; + for (let n = tokens.length; n >= 1; n--) { + if (FRAMEWORK_LABELS[tokens.slice(0, n).join('-')]) { + fwTokens = n; + break; + } + } + const baseLabel = getFrameworkLabel(tokens.slice(0, fwTokens).join('-')); + // Trailing descriptors keep their spec-method labels (M3's `mtp` renders as + // "EAGLE"); anything unknown is title-cased instead of shouted in caps. + const suffixLabels = tokens.slice(fwTokens).map((t) => { + if (t === 'mtp') return resolveFrameworkPartLabel(MODEL_PREFIX_MAPPING[model], 'mtp'); + return FRAMEWORK_LABELS[t] ?? t.charAt(0).toUpperCase() + t.slice(1); + }); + const frameworkLabel = [baseLabel, ...suffixLabels].join(', '); return `${gpu.toUpperCase()} (${frameworkLabel}) ${MODEL_PREFIX_MAPPING[model]} ${getPrecisionLabel(precision as Precision)}`; }