Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ui): make eval section header draggable #2637

Merged
merged 18 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ export const CompareEvaluationsPage: React.FC<
export const CompareEvaluationsPageContent: React.FC<
CompareEvaluationsPageProps
> = props => {
const [baselineEvaluationCallId, setBaselineEvaluationCallId] =
React.useState<string | null>(null);
const [comparisonDimensions, setComparisonDimensions] =
React.useState<ComparisonDimensionsType | null>(null);

Expand All @@ -104,14 +102,6 @@ export const CompareEvaluationsPageContent: React.FC<
[comparisonDimensions]
);

React.useEffect(() => {
// Only update the baseline if we are switching evaluations, if there
// is more than 1, we are in the compare view and baseline is auto set
if (props.evaluationCallIds.length === 1) {
setBaselineEvaluationCallId(props.evaluationCallIds[0]);
}
}, [props.evaluationCallIds]);

if (props.evaluationCallIds.length === 0) {
return <div>No evaluations to compare</div>;
}
Expand All @@ -120,13 +110,11 @@ export const CompareEvaluationsPageContent: React.FC<
<CompareEvaluationsProvider
entity={props.entity}
project={props.project}
initialEvaluationCallIds={props.evaluationCallIds}
selectedMetrics={props.selectedMetrics}
setSelectedMetrics={props.setSelectedMetrics}
initialEvaluationCallIds={props.evaluationCallIds}
baselineEvaluationCallId={baselineEvaluationCallId ?? undefined}
comparisonDimensions={comparisonDimensions ?? undefined}
onEvaluationCallIdsUpdate={props.onEvaluationCallIdsUpdate}
setBaselineEvaluationCallId={setBaselineEvaluationCallId}
setComparisonDimensions={setComparisonDimensionsAndClearInputDigest}
selectedInputDigest={selectedInputDigest ?? undefined}
setSelectedInputDigest={setSelectedInputDigest}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@ import {ComparisonDimensionsType} from './ecpState';

const CompareEvaluationsContext = React.createContext<{
state: EvaluationComparisonState;
setBaselineEvaluationCallId: React.Dispatch<
React.SetStateAction<string | null>
>;
setComparisonDimensions: React.Dispatch<
React.SetStateAction<ComparisonDimensionsType | null>
>;
setSelectedInputDigest: React.Dispatch<React.SetStateAction<string | null>>;
setSelectedMetrics: (newModel: Record<string, boolean>) => void;
addEvaluationCall: (newCallId: string) => void;
removeEvaluationCall: (callId: string) => void;
setEvaluationCallOrder: (newCallIdOrder: string[]) => void;
} | null>(null);

export const useCompareEvaluationsState = () => {
Expand All @@ -33,34 +31,26 @@ export const useCompareEvaluationsState = () => {
export const CompareEvaluationsProvider: React.FC<{
entity: string;
project: string;
initialEvaluationCallIds: string[];
selectedMetrics: Record<string, boolean> | null;
setSelectedMetrics: (newModel: Record<string, boolean>) => void;

initialEvaluationCallIds: string[];
onEvaluationCallIdsUpdate: (newEvaluationCallIds: string[]) => void;
setBaselineEvaluationCallId: React.Dispatch<
React.SetStateAction<string | null>
>;
setComparisonDimensions: React.Dispatch<
React.SetStateAction<ComparisonDimensionsType | null>
>;
setSelectedInputDigest: React.Dispatch<React.SetStateAction<string | null>>;
baselineEvaluationCallId?: string;
comparisonDimensions?: ComparisonDimensionsType;
selectedInputDigest?: string;
}> = ({
entity,
project,
initialEvaluationCallIds,
selectedMetrics,
setSelectedMetrics,

initialEvaluationCallIds,
onEvaluationCallIdsUpdate,
setBaselineEvaluationCallId,
setComparisonDimensions,

setSelectedInputDigest,
baselineEvaluationCallId,
comparisonDimensions,
selectedInputDigest,
children,
Expand All @@ -77,7 +67,6 @@ export const CompareEvaluationsProvider: React.FC<{
entity,
project,
evaluationCallIds,
baselineEvaluationCallId,
comparisonDimensions,
selectedInputDigest,
selectedMetrics ?? undefined
Expand All @@ -89,7 +78,6 @@ export const CompareEvaluationsProvider: React.FC<{
}
return {
state: initialState.result,
setBaselineEvaluationCallId,
setComparisonDimensions,
setSelectedInputDigest,
setSelectedMetrics,
Expand All @@ -105,14 +93,17 @@ export const CompareEvaluationsProvider: React.FC<{
setEvaluationCallIds(newEvaluationCallIds);
onEvaluationCallIdsUpdate(newEvaluationCallIds);
},
setEvaluationCallOrder: (newCallIdOrder: string[]) => {
setEvaluationCallIds(newCallIdOrder);
onEvaluationCallIdsUpdate(newCallIdOrder);
},
};
}, [
initialState.loading,
initialState.result,
setEvaluationCallIds,
evaluationCallIds,
onEvaluationCallIdsUpdate,
setEvaluationCallIds,
setBaselineEvaluationCallId,
setComparisonDimensions,
setSelectedInputDigest,
setSelectedMetrics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import {getMetricIds} from './ecpUtil';
export type EvaluationComparisonState = {
// The normalized data for the evaluations
data: EvaluationComparisonData;
// The evaluation call id of the baseline model
baselineEvaluationCallId: string;
// The dimensions to compare & filter results
comparisonDimensions?: ComparisonDimensionsType;
// The current digest which is in view
selectedInputDigest?: string;
// The selected metrics to display
selectedMetrics?: Record<string, boolean>;
// Ordered call Ids
evaluationCallIdsOrdered: string[];
};

export type ComparisonDimensionsType = Array<{
Expand All @@ -43,12 +43,14 @@ export const useEvaluationComparisonState = (
entity: string,
project: string,
evaluationCallIds: string[],
baselineEvaluationCallId?: string,
comparisonDimensions?: ComparisonDimensionsType,
selectedInputDigest?: string,
selectedMetrics?: Record<string, boolean>
): Loadable<EvaluationComparisonState> => {
const data = useEvaluationComparisonData(entity, project, evaluationCallIds);
const orderedCallIds = useMemo(() => {
return getCallIdsOrderedForQuery(evaluationCallIds);
}, [evaluationCallIds]);
const data = useEvaluationComparisonData(entity, project, orderedCallIds);

const value = useMemo(() => {
if (data.result == null || data.loading) {
Expand Down Expand Up @@ -92,42 +94,45 @@ export const useEvaluationComparisonState = (
loading: false,
result: {
data: data.result,
baselineEvaluationCallId:
baselineEvaluationCallId ?? evaluationCallIds[0],
comparisonDimensions: newComparisonDimensions,
selectedInputDigest,
selectedMetrics,
evaluationCallIdsOrdered: evaluationCallIds,
},
};
}, [
data.result,
data.loading,
baselineEvaluationCallId,
evaluationCallIds,
comparisonDimensions,
selectedInputDigest,
selectedMetrics,
evaluationCallIds,
]);

return value;
};

export const getOrderedCallIds = (state: EvaluationComparisonState) => {
return Array.from(state.evaluationCallIdsOrdered);
};

export const getBaselineCallId = (state: EvaluationComparisonState) => {
return getOrderedCallIds(state)[0];
};

/**
* Should use this over keys of `state.data.evaluationCalls` because it ensures the baseline
* evaluation call is first.
* Sort call IDs to ensure consistent order for memoized query params
*/
export const getOrderedCallIds = (state: EvaluationComparisonState) => {
const initial = Object.keys(state.data.evaluationCalls);
moveItemToFront(initial, state.baselineEvaluationCallId);
return initial;
const getCallIdsOrderedForQuery = (callIds: string[]) => {
return Array.from(callIds).sort();
};

/**
* Should use this over keys of `state.data.models` because it ensures the baseline model is first.
*/
export const getOrderedModelRefs = (state: EvaluationComparisonState) => {
const baselineRef =
state.data.evaluationCalls[state.baselineEvaluationCallId].modelRef;
const baselineCallId = getBaselineCallId(state);
const baselineRef = state.data.evaluationCalls[baselineCallId].modelRef;
const refs = Object.keys(state.data.models);
// Make sure the baseline model is first
moveItemToFront(refs, baselineRef);
Expand All @@ -145,3 +150,29 @@ const moveItemToFront = <T>(arr: T[], item: T): T[] => {
}
return arr;
};

export const getOrderedEvalsWithNewBaseline = (
evaluationCallIds: string[],
newBaselineCallId: string
) => {
return moveItemToFront(evaluationCallIds, newBaselineCallId);
};

export const swapEvaluationCalls = (
evaluationCallIds: string[],
ndx1: number,
ndx2: number
): string[] => {
return swapArrayItems(evaluationCallIds, ndx1, ndx2);
};

const swapArrayItems = <T>(arr: T[], ndx1: number, ndx2: number): T[] => {
if (ndx1 < 0 || ndx2 < 0 || ndx1 >= arr.length || ndx2 >= arr.length) {
throw new Error('Index out of bounds');
}
const newArr = [...arr];
const from = newArr[ndx1];
newArr[ndx1] = newArr[ndx2];
newArr[ndx2] = from;
return newArr;
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type EvaluationComparisonData = {
};

// EvaluationCalls are the specific calls of an evaluation.
// The visual order of the evaluation calls is determined by the order of the keys.
evaluationCalls: {
[callId: string]: EvaluationCall;
};
Expand Down
Loading
Loading