Skip to content

Commit ceed84c

Browse files
committed
fix(inference): exclude eagle from STP filter; skip quick filters on trends tab
1 parent 379f772 commit ceed84c

3 files changed

Lines changed: 40 additions & 6 deletions

File tree

packages/app/src/components/inference/InferenceContext.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ import { filterRunsByModel, getDisplayLabel } from '@/lib/utils';
5959

6060
import { useChartData } from './hooks/useChartData';
6161
import { resolveComparisonEntries } from './utils/comparisonEntry';
62-
import type { DisaggMode, QuickFilters, SpecMode } from './utils/quickFilters';
62+
import {
63+
EMPTY_QUICK_FILTERS,
64+
type DisaggMode,
65+
type QuickFilters,
66+
type SpecMode,
67+
} from './utils/quickFilters';
6368

6469
/** @internal Exported for test provider wrapping only. */
6570
export const InferenceContext = createContext<InferenceChartContextType | undefined>(undefined);
@@ -181,6 +186,10 @@ export function InferenceProvider({
181186
}),
182187
[quickFilterVendors, quickFilterFrameworks, quickFilterDisagg, quickFilterSpec],
183188
);
189+
// The Historical Trends tab hides the quick-filter pills (hideGpuComparison), so
190+
// don't silently narrow its chart with selections carried in via share links or
191+
// the inference tab — there would be no pill to clear them.
192+
const dataQuickFilters = activeTab === 'historical' ? EMPTY_QUICK_FILTERS : quickFilters;
184193
const { highContrast, setHighContrast, isLegendExpanded, setIsLegendExpanded } = useChartUIState({
185194
urlPrefix: 'i_',
186195
});
@@ -303,7 +312,7 @@ export function InferenceProvider({
303312
latestDate,
304313
compareGpuPair ?? null,
305314
asOfRunId,
306-
quickFilters,
315+
dataQuickFilters,
307316
);
308317

309318
// For GPU comparison date picker — use shared availability data from global filters

packages/app/src/components/inference/utils/quickFilters.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ describe('matchesQuickFilters', () => {
152152
expect(matchesQuickFilters(point({ hwKey: 'h100_vllm' }), stpFilter)).toBe(true);
153153
});
154154

155+
it('treats non-standard spec methods (e.g. eagle) as neither MTP nor STP', () => {
156+
const eagle = point({ hwKey: 'h200_trt_eagle', spec_decoding: 'eagle' });
157+
expect(matchesQuickFilters(eagle, filters({ spec: ['mtp'] }))).toBe(false);
158+
expect(matchesQuickFilters(eagle, filters({ spec: ['stp'] }))).toBe(false);
159+
// Excluded under either spec selection, but unconstrained when spec is empty.
160+
expect(matchesQuickFilters(eagle, filters({ spec: ['mtp', 'stp'] }))).toBe(false);
161+
expect(matchesQuickFilters(eagle, EMPTY_QUICK_FILTERS)).toBe(true);
162+
// An eagle-only point contributes to neither spec pill.
163+
expect(computeAvailableQuickFilters([eagle]).spec).toEqual([]);
164+
});
165+
155166
it('ANDs categories together', () => {
156167
const f = filters({ vendors: ['AMD'], disagg: ['disagg'], spec: ['stp'] });
157168
expect(

packages/app/src/components/inference/utils/quickFilters.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ export function computeAvailableQuickFilters(
8383
if (fam) frameworks.add(fam);
8484
if (p.disagg) hasDisagg = true;
8585
else hasAgg = true;
86-
if (pointIsMtp(p)) hasMtp = true;
87-
else hasStp = true;
86+
const specMode = pointSpecMode(p);
87+
if (specMode === 'mtp') hasMtp = true;
88+
else if (specMode === 'stp') hasStp = true;
8889
}
8990
const disagg: DisaggMode[] = [];
9091
if (hasAgg) disagg.push('agg');
@@ -117,6 +118,19 @@ function pointIsMtp(point: InferenceData): boolean {
117118
return point.spec_decoding === 'mtp' || String(point.hwKey).endsWith('_mtp');
118119
}
119120

121+
/**
122+
* Classify a point for the spec-decoding filter, or `null` when it is neither
123+
* plain MTP nor standard decoding. STP means *standard* (no speculative method),
124+
* which the DB marks `none` (and the hwKey carries no spec suffix). Other methods
125+
* such as EAGLE are neither MTP nor STP, so they must not fall through to STP.
126+
*/
127+
function pointSpecMode(point: InferenceData): SpecMode | null {
128+
if (pointIsMtp(point)) return 'mtp';
129+
const s = point.spec_decoding;
130+
if (s === 'none' || s === '' || s === undefined || s === null) return 'stp';
131+
return null;
132+
}
133+
120134
/** Whether a single data point satisfies every active quick-filter category. */
121135
export function matchesQuickFilters(point: InferenceData, f: QuickFilters): boolean {
122136
if (f.vendors.length > 0) {
@@ -132,8 +146,8 @@ export function matchesQuickFilters(point: InferenceData, f: QuickFilters): bool
132146
if (!f.disagg.includes(mode)) return false;
133147
}
134148
if (f.spec.length > 0) {
135-
const mode: SpecMode = pointIsMtp(point) ? 'mtp' : 'stp';
136-
if (!f.spec.includes(mode)) return false;
149+
const mode = pointSpecMode(point);
150+
if (!mode || !f.spec.includes(mode)) return false;
137151
}
138152
return true;
139153
}

0 commit comments

Comments
 (0)