Skip to content

Commit

Permalink
feat(ui): add filter condition snippets (#2049)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeldking authored Jan 9, 2024
1 parent 6c64bea commit 567fa54
Showing 1 changed file with 137 additions and 1 deletion.
138 changes: 137 additions & 1 deletion app/src/pages/tracing/SpanFilterConditionField.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {
startTransition,
useCallback,
useDeferredValue,
useEffect,
useState,
Expand All @@ -14,13 +15,18 @@ import { css } from "@emotion/react";

import {
AddonBefore,
Button,
Field,
Flex,
Form,
HelpTooltip,
Icon,
Icons,
PopoverTrigger,
Text,
TooltipTrigger,
TriggerWrap,
View,
} from "@arizeai/components";

import { useTheme } from "@phoenix/contexts";
Expand Down Expand Up @@ -51,7 +57,7 @@ const fieldCSS = css`
border-radius: var(--ac-global-rounding-small);
background-color: var(--ac-global-input-field-background-color);
transition: all 0.2s ease-in-out;
overflow: hidden;
overflow-x: hidden;
&:hover,
&[data-is-focused="true"] {
border-color: var(--ac-global-input-field-border-color-active);
Expand All @@ -60,6 +66,7 @@ const fieldCSS = css`
&[data-is-invalid="true"] {
border-color: var(--ac-global-color-danger);
}
box-sizing: border-box;
`;

function filterConditionCompletions(context: CompletionContext) {
Expand Down Expand Up @@ -229,6 +236,16 @@ export function SpanFilterConditionField(props: SpanFilterConditionFieldProps) {
const deferredFilterCondition = useDeferredValue(filterCondition);
const { theme } = useTheme();
const codeMirrorTheme = theme === "dark" ? nord : undefined;
const onAddFilterConditionSnippet = useCallback(
(additionalCondition: string) => {
if (filterCondition.length > 0) {
setFilterCondition(`${filterCondition} and ${additionalCondition}`);
} else {
setFilterCondition(additionalCondition);
}
},
[filterCondition, setFilterCondition]
);

useEffect(() => {
isConditionValid(deferredFilterCondition).then((result) => {
Expand Down Expand Up @@ -288,6 +305,25 @@ export function SpanFilterConditionField(props: SpanFilterConditionFieldProps) {
>
<Icon svg={<Icons.CloseCircleOutline />} />
</button>
<PopoverTrigger placement="bottom right">
<TriggerWrap>
<button
css={css`
color: var(--ac-global-text-color-700);
background-color: var(--ac-global-color-grey-400);
padding-left: var(--ac-global-dimension-static-size-100);
padding-right: var(--ac-global-dimension-static-size-100);
height: 100%;
`}
className="button--reset"
>
<Icon svg={<Icons.PlusCircleOutline />} />
</button>
</TriggerWrap>
<FilterConditionBuilder
onAddFilterConditionSnippet={onAddFilterConditionSnippet}
/>
</PopoverTrigger>
</Flex>
<TooltipTrigger isOpen={hasError && isFocused} placement="bottom">
<TriggerWrap>
Expand All @@ -304,3 +340,103 @@ export function SpanFilterConditionField(props: SpanFilterConditionFieldProps) {
</div>
);
}

/**
* Component to build up a filter condition via snippets of conditions
* E.x. filter by kind, filter by token count, etc.
*/
function FilterConditionBuilder(props: {
onAddFilterConditionSnippet: (condition: string) => void;
}) {
const { onAddFilterConditionSnippet } = props;
return (
<View
width="500px"
paddingTop="size-200"
paddingStart="size-200"
paddingEnd="size-200"
borderRadius="medium"
borderWidth="thin"
borderColor="light"
backgroundColor="light"
>
<Form>
<FilterConditionSnippet
key="kind"
label="filter by kind"
initialSnippet="span_kind == 'LLM'"
onAddFilterConditionSnippet={onAddFilterConditionSnippet}
/>
<FilterConditionSnippet
key="token_count"
label="filter by token count"
initialSnippet="cumulative_token_count.total > 1000"
onAddFilterConditionSnippet={onAddFilterConditionSnippet}
/>
<FilterConditionSnippet
key="eval_label"
label="filter by evaluation label"
initialSnippet="evals['Hallucination'].label == 'hallucinated'"
onAddFilterConditionSnippet={onAddFilterConditionSnippet}
/>
<FilterConditionSnippet
key="eval_score"
label="filter by evaluation score"
initialSnippet="evals['Hallucination'].score < 1"
onAddFilterConditionSnippet={onAddFilterConditionSnippet}
/>
</Form>
</View>
);
}

/**
* A snippet of filter condition that can be added to the filter condition field
*/
function FilterConditionSnippet(props: {
label: string;
initialSnippet: string;
onAddFilterConditionSnippet: (condition: string) => void;
}) {
const { initialSnippet, onAddFilterConditionSnippet } = props;
const [snippet, setSnippet] = useState<string>(initialSnippet);
const { theme } = useTheme();
const codeMirrorTheme = theme === "light" ? undefined : nord;
return (
<Field label={props.label}>
<Flex direction="row" width="100%" gap="size-100">
<div
css={css(
fieldCSS,
css`
flex: 1 1 auto;
`
)}
>
<CodeMirror
value={snippet}
basicSetup={{
lineNumbers: false,
foldGutter: false,
bracketMatching: true,
syntaxHighlighting: true,
highlightActiveLine: false,
highlightActiveLineGutter: false,
}}
extensions={[python()]}
editable={true}
onChange={setSnippet}
theme={codeMirrorTheme}
css={codeMirrorCSS}
/>
</div>
<Button
title="Add to filter condition"
variant="default"
onClick={() => onAddFilterConditionSnippet(snippet)}
icon={<Icon svg={<Icons.PlusCircleOutline />} />}
/>
</Flex>
</Field>
);
}

0 comments on commit 567fa54

Please sign in to comment.