From adfad73d8a814a1c286d99184b638c591efdf1ef Mon Sep 17 00:00:00 2001 From: gtarpenning Date: Tue, 29 Oct 2024 14:28:51 -0700 Subject: [PATCH] wip -- working with json-schema --- weave-js/src/components/Form/TextField.tsx | 3 + .../feedback/HumanFeedback/HumanFeedback.tsx | 41 +++++------ .../HumanFeedback/HumanFeedbackSidebar.tsx | 24 ++++--- .../HumanFeedback/humanFeedbackTypes.ts | 43 ++--------- .../feedback/HumanFeedback/tsHumanFeedback.ts | 71 ++++++++----------- .../Home/Browse3/pages/CallPage/CallPage.tsx | 8 +-- .../pages/wfReactInterface/constants.ts | 2 +- 7 files changed, 78 insertions(+), 114 deletions(-) diff --git a/weave-js/src/components/Form/TextField.tsx b/weave-js/src/components/Form/TextField.tsx index f9bdd0bc8b9..b3d8f952ff5 100644 --- a/weave-js/src/components/Form/TextField.tsx +++ b/weave-js/src/components/Form/TextField.tsx @@ -35,6 +35,7 @@ type TextFieldProps = { type?: string; autoComplete?: string; dataTest?: string; + step?: number; }; export const TextField = ({ @@ -55,6 +56,7 @@ export const TextField = ({ type, autoComplete, dataTest, + step, }: TextFieldProps) => { const textFieldSize = size ?? 'medium'; const leftPaddingForIcon = textFieldSize === 'medium' ? 'pl-34' : 'pl-36'; @@ -129,6 +131,7 @@ export const TextField = ({ type={type} autoComplete={autoComplete} data-test={dataTest} + step={step} /> {extraActions} diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedback.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedback.tsx index 9411236fbe2..8ce82f40fb0 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedback.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedback.tsx @@ -15,23 +15,22 @@ import React, { } from 'react'; import { CellValueString } from '../../../Browse2/CellValueString'; -import { parseRefMaybe } from '../../../Browse2/SmallRef'; import {useWFHooks} from '../../pages/wfReactInterface/context'; import {useGetTraceServerClientContext} from '../../pages/wfReactInterface/traceServerClientContext'; import { FeedbackCreateError, FeedbackCreateSuccess, } from '../../pages/wfReactInterface/traceServerClientTypes'; -import { CategoricalFeedback, HumanAnnotationPayload, HumanFeedback,NumericalFeedback, tsFeedbackType} from './humanFeedbackTypes'; +import { HumanAnnotationPayload, HumanFeedback, tsHumanFeedbackColumn} from './humanFeedbackTypes'; import { parseRef } from '@wandb/weave/react'; // Constants -const STRUCTURED_FEEDBACK_TYPE = 'wandb.human_annotation.1'; +const HUMAN_FEEDBACK_TYPE = 'wandb.human_annotation.1'; const MAGIC_FEEDBACK_TYPES = { - NUMERICAL: 'NumericalFeedback', - TEXT: 'TextFeedback', - BOOLEAN: 'BinaryFeedback', - CATEGORICAL: 'CategoricalFeedback', + NUMERICAL: 'number', + TEXT: 'text', + BOOLEAN: 'boolean', + CATEGORICAL: 'categorical', } const DEBOUNCE_VAL = 200; @@ -40,7 +39,7 @@ interface HumanFeedbackProps { entity: string; project: string; viewer: string | null; - sfData: tsFeedbackType; + hfColumn: tsHumanFeedbackColumn; callRef: string; readOnly?: boolean; focused?: boolean; @@ -51,9 +50,10 @@ const createFeedbackRequest = ( props: HumanFeedbackProps, value: any, ) => { - const parsedRef = parseRef(props.sfData.ref); + const ref = props.hfColumn.ref; + const parsedRef = parseRef(ref); const humanAnnotationPayload: HumanAnnotationPayload = { - annotation_column_ref: props.sfData.ref, + annotation_column_ref: ref, value: { [parsedRef.artifactName]: { [parsedRef?.artifactVersion]: value @@ -65,7 +65,7 @@ const createFeedbackRequest = ( project_id: `${props.entity}/${props.project}`, weave_ref: props.callRef, creator: props.viewer, - feedback_type: STRUCTURED_FEEDBACK_TYPE, + feedback_type: HUMAN_FEEDBACK_TYPE, payload: humanAnnotationPayload, sort_by: [{created_at: 'desc'}], }; @@ -78,9 +78,10 @@ const renderFeedbackComponent = ( onAddFeedback: (value: any) => Promise, foundValue: string | number | null, ) => { - switch (props.sfData._type) { + // TODO validation on json_schema + switch (props.hfColumn.json_schema.type) { case MAGIC_FEEDBACK_TYPES.NUMERICAL: - const numericalFeedback = props.sfData as NumericalFeedback; + const numericalFeedback = props.hfColumn.json_schema; return ( ); case MAGIC_FEEDBACK_TYPES.CATEGORICAL: - const categoricalFeedback = props.sfData as CategoricalFeedback; + const categoricalFeedback = props.hfColumn.json_schema; return ( - feedback.payload.annotation_column_ref === props.sfData.ref; + feedback.payload.annotation_column_ref === props.hfColumn.ref; const currFeedback = query.result?.filter( (feedback: HumanFeedback) => @@ -201,7 +202,7 @@ export const HumanFeedbackCell: React.FC< } setFoundFeedback(currFeedback); - }, [query?.result, query?.loading, props.sfData]); + }, [query?.result, query?.loading, props.hfColumn]); // userId -> objectId -> objectHash : value const combinedFeedback = foundFeedback.reduce((acc, feedback) => { @@ -211,9 +212,7 @@ export const HumanFeedbackCell: React.FC< }; }, {}) as Record>>; - // rawValues is an array of values from the feedback - const parsedRef = parseRef(props.sfData.ref); - + const parsedRef = parseRef(props.hfColumn.ref); const rawValues = useMemo(() => { let values = []; for (const payload of Object.values(combinedFeedback)) { @@ -224,7 +223,6 @@ export const HumanFeedbackCell: React.FC< }, [combinedFeedback, parsedRef]); const viewerFeedbackVal = props.viewer ? combinedFeedback[props.viewer]?.[parsedRef.artifactName]?.[parsedRef.artifactVersion] : null; - if (query?.loading) { return ; } @@ -249,12 +247,14 @@ export const NumericalFeedbackColumn = ({ onAddFeedback, defaultValue, focused, + isInteger, }: { min: number; max: number; onAddFeedback?: (value: number) => Promise; defaultValue: number | null; focused?: boolean; + isInteger?: boolean; }) => { const [value, setValue] = useState( defaultValue ?? undefined @@ -295,6 +295,7 @@ export const NumericalFeedbackColumn = ({ value={value?.toString() ?? ''} onChange={onValueChange} placeholder="..." + step={isInteger ? 1 : 0.001} errorState={error} /> diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedbackSidebar.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedbackSidebar.tsx index 9a214085a34..1be0609e3f2 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedbackSidebar.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/HumanFeedbackSidebar.tsx @@ -4,18 +4,18 @@ import React, {useState} from 'react'; import {Icon} from '../../../../../Icon'; import {HumanFeedbackCell} from './HumanFeedback'; -import {tsHumanFeedbackSpec} from './humanFeedbackTypes'; +import {tsHumanFeedbackColumn} from './humanFeedbackTypes'; import { useViewerInfo } from '@wandb/weave/common/hooks/useViewerInfo'; type HumanFeedbackSidebarProps = { - feedbackOptions: tsHumanFeedbackSpec | null; + feedbackColumns: tsHumanFeedbackColumn[]; callID: string; entity: string; project: string; }; export const HumanFeedbackSidebar = ({ - feedbackOptions, + feedbackColumns, callID, entity, project, @@ -24,12 +24,9 @@ export const HumanFeedbackSidebar = ({ const {loading: loadingUserInfo, userInfo} = useViewerInfo(); const [isExpanded, setIsExpanded] = useState(true); + const feedbackCellCount = feedbackColumns.length ?? 0; - const feedbackFields = feedbackOptions?.feedback_fields; - const feedbackSpecRef = feedbackOptions?.ref; - const feedbackCellCount = feedbackFields?.length ?? 0; - - if (loadingUserInfo || !feedbackSpecRef) { + if (loadingUserInfo) { return null; } @@ -56,15 +53,20 @@ export const HumanFeedbackSidebar = ({ {isExpanded && (
- {feedbackFields?.map((field, index) => ( + {feedbackColumns?.map((field, index) => (

- {field.display_name} + {field.name}

+ {field.description && ( +

+ {field.description} +

+ )}
; + unique_among_creators?: boolean; + op_scope?: string[]; }; export type HumanAnnotationPayload = { diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/tsHumanFeedback.ts b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/tsHumanFeedback.ts index 81c96c176c1..ad63d90663a 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/tsHumanFeedback.ts +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/feedback/HumanFeedback/tsHumanFeedback.ts @@ -3,72 +3,59 @@ import {useEffect, useMemo, useState} from 'react'; import {useWFHooks} from '../../pages/wfReactInterface/context'; import {objectVersionKeyToRefUri} from '../../pages/wfReactInterface/utilities'; import {ObjectVersionSchema} from '../../pages/wfReactInterface/wfDataModelHooksInterface'; -import {tsHumanFeedbackSpec} from './humanFeedbackTypes'; +import {tsHumanFeedbackColumn} from './humanFeedbackTypes'; -const useResolveTypeObjects = (typeRefs: string[]) => { - const {useRefsData} = useWFHooks(); - const refsData = useRefsData(typeRefs); - return useMemo(() => { - if (refsData.loading || refsData.result == null) { - return null; - } - const refDataWithRefs = refsData.result.map((x, i) => ({ - ...x, - ref: typeRefs[i], - })); - return refDataWithRefs; - }, [refsData.loading, refsData.result]); -}; +// const useResolveTypeObjects = (typeRefs: string[]) => { +// const {useRefsData} = useWFHooks(); +// const refsData = useRefsData(typeRefs); +// return useMemo(() => { +// if (refsData.loading || refsData.result == null) { +// return null; +// } +// const refDataWithRefs = refsData.result.map((x, i) => ({ +// ...x, +// ref: typeRefs[i], +// })); +// return refDataWithRefs; +// }, [refsData.loading, refsData.result]); +// }; export const useHumanFeedbackOptions = ( entity: string, project: string -): tsHumanFeedbackSpec | null => { +): tsHumanFeedbackColumn[] => { const {useRootObjectVersions} = useWFHooks(); - const [latestSpec, setLatestSpec] = useState( + const [cols, setCols] = useState( null ); - const humanFeedbackObjects = useRootObjectVersions( + const humanAnnotationColumns = useRootObjectVersions( entity, project, { - baseObjectClasses: ['HumanFeedback'], + baseObjectClasses: ['HumanAnnotationColumn'], latestOnly: true, }, undefined, // limit false // metadataOnly ); - // TODO: this is not actually tsHumanFeedbackSpec, it's HumanFeedbackSpec - // we need to add the refs for each of the feedback fields - const feedbackFieldRefs = latestSpec?.val?.feedback_fields ?? [] - const feedbackFields = useResolveTypeObjects(feedbackFieldRefs); - - console.log('feedbackFields', feedbackFields); useEffect(() => { - if (humanFeedbackObjects.loading || humanFeedbackObjects.result == null) { - return; - } - // sort by createdAtMs, most recent first - const spec = humanFeedbackObjects.result - ?.sort((a, b) => b.createdAtMs - a.createdAtMs) - .pop(); - if (!spec) { + if (humanAnnotationColumns.loading || humanAnnotationColumns.result == null) { return; } - setLatestSpec(spec); - }, [humanFeedbackObjects.loading, humanFeedbackObjects.result]); + setCols(humanAnnotationColumns.result); + }, [humanAnnotationColumns.loading, humanAnnotationColumns.result]); return useMemo(() => { - if (latestSpec == null || feedbackFields == null) { - return null; + if (cols == null) { + return []; } - return { - feedback_fields: feedbackFields, - ref: objectVersionKeyToRefUri(latestSpec), - }; - }, [latestSpec, feedbackFields]); + return cols.map((col) => ({ + ...col.val, + ref: objectVersionKeyToRefUri(col), + })); + }, [cols]); }; diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallPage/CallPage.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallPage/CallPage.tsx index 59e11018c9b..49173645e57 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallPage/CallPage.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallPage/CallPage.tsx @@ -10,8 +10,6 @@ import {Tailwind} from '../../../../../Tailwind'; import {Browse2OpDefCode} from '../../../Browse2/Browse2OpDefCode'; import {TRACETREE_PARAM, useWeaveflowCurrentRouteContext} from '../../context'; import {FeedbackGrid} from '../../feedback/FeedbackGrid'; -import {HumanFeedbackSidebar} from '../../feedback/HumanFeedback/HumanFeedbackSidebar'; -import {useHumanFeedbackOptions} from '../../feedback/HumanFeedback/tsHumanFeedback'; import {NotFoundPanel} from '../../NotFoundPanel'; import {isCallChat} from '../ChatView/hooks'; import {isEvaluateOp} from '../common/heuristics'; @@ -30,6 +28,8 @@ import {CallDetails} from './CallDetails'; import {CallOverview} from './CallOverview'; import {CallSummary} from './CallSummary'; import {CallTraceView, useCallFlattenedTraceTree} from './CallTraceView'; +import { useHumanFeedbackOptions } from '../../feedback/HumanFeedback/tsHumanFeedback'; +import { HumanFeedbackSidebar } from '../../feedback/HumanFeedback/HumanFeedbackSidebar'; export const CallPage: FC<{ entity: string; project: string; @@ -189,7 +189,7 @@ const CallPageInnerVertical: FC<{ ); }, [currentRouter, history, path, showTraceTree, call, showFeedbackExpand]); const feedbackOptions = useHumanFeedbackOptions(call.entity, call.project); - + const tree = useCallFlattenedTraceTree(call, path ?? null); const {rows, expandKeys, loading, costLoading, selectedCall} = tree; const callComplete = useCall({ @@ -246,7 +246,7 @@ const CallPageInnerVertical: FC<{ isFeedbackSidebarOpen={showFeedbackExpand} feedbackSidebarContent={