diff --git a/chainforge/react-server/src/AlertModal.tsx b/chainforge/react-server/src/AlertModal.tsx index a270273..aeb60a2 100644 --- a/chainforge/react-server/src/AlertModal.tsx +++ b/chainforge/react-server/src/AlertModal.tsx @@ -8,36 +8,38 @@ const ALERT_MODAL_STYLE = { root: { position: "relative", left: "-5%" }, } as Styles; -interface AlertModalHandles { +export interface AlertModalHandles { trigger: (msg?: string) => void; } -const AlertModal = forwardRef(function AlertModal(props, ref) { - // Mantine modal popover for alerts - const [opened, { open, close }] = useDisclosure(false); - const [alertMsg, setAlertMsg] = useState(""); +const AlertModal = forwardRef( + function AlertModal(props, ref) { + // Mantine modal popover for alerts + const [opened, { open, close }] = useDisclosure(false); + const [alertMsg, setAlertMsg] = useState(""); - // This gives the parent access to triggering the modal alert - const trigger = (msg?: string) => { - if (!msg) msg = "Unknown error."; - console.error(msg); - setAlertMsg(msg); - open(); - }; - useImperativeHandle(ref, () => ({ - trigger, - })); + // This gives the parent access to triggering the modal alert + const trigger = (msg?: string) => { + if (!msg) msg = "Unknown error."; + console.error(msg); + setAlertMsg(msg); + open(); + }; + useImperativeHandle(ref, () => ({ + trigger, + })); - return ( - -

{alertMsg}

-
- ); -}); + return ( + +

{alertMsg}

+
+ ); + }, +); export default AlertModal; diff --git a/chainforge/react-server/src/BaseNode.tsx b/chainforge/react-server/src/BaseNode.tsx index 78a46de..1596614 100644 --- a/chainforge/react-server/src/BaseNode.tsx +++ b/chainforge/react-server/src/BaseNode.tsx @@ -11,8 +11,8 @@ import useStore from "./store"; interface BaseNodeProps { children: React.ReactNode; // For components, HTML elements, text, etc. - classNames: string; nodeId: string; + classNames?: string; style?: React.CSSProperties; // Optional prop for inline styles } diff --git a/chainforge/react-server/src/CommentNode.js b/chainforge/react-server/src/CommentNode.tsx similarity index 100% rename from chainforge/react-server/src/CommentNode.js rename to chainforge/react-server/src/CommentNode.tsx diff --git a/chainforge/react-server/src/NodeLabelComponent.js b/chainforge/react-server/src/NodeLabelComponent.tsx similarity index 83% rename from chainforge/react-server/src/NodeLabelComponent.js rename to chainforge/react-server/src/NodeLabelComponent.tsx index 7e4cfb4..5b7da3e 100644 --- a/chainforge/react-server/src/NodeLabelComponent.js +++ b/chainforge/react-server/src/NodeLabelComponent.tsx @@ -5,16 +5,32 @@ import React, { useEffect, useCallback, } from "react"; -import useStore from "./store"; +import { Tooltip } from "@mantine/core"; import { EditText } from "react-edit-text"; import "react-edit-text/dist/index.css"; -import StatusIndicator from "./StatusIndicatorComponent"; -import AlertModal from "./AlertModal"; +import useStore from "./store"; +import StatusIndicator, { Status } from "./StatusIndicatorComponent"; +import AlertModal, { AlertModalHandles } from "./AlertModal"; import AreYouSureModal from "./AreYouSureModal"; -import { Tooltip } from "@mantine/core"; +interface NodeLabelProps { + title: string; + nodeId: string; + icon: string; + onEdit?: () => void; + onSave?: () => void; + editable?: boolean; + status?: Status; + isRunning?: boolean; + alertModal?: React.Ref; + customButtons?: React.ReactElement[]; + handleRunClick?: () => void; + handleStopClick?: (nodeId: string) => void; + handleRunHover?: () => void; + runButtonTooltip?: string; +} -export default function NodeLabel({ +export const NodeLabel: React.FC = ({ title, nodeId, icon, @@ -29,10 +45,10 @@ export default function NodeLabel({ handleStopClick, handleRunHover, runButtonTooltip, -}) { +}) => { const setDataPropsForNode = useStore((state) => state.setDataPropsForNode); - const [statusIndicator, setStatusIndicator] = useState("none"); - const [runButton, setRunButton] = useState("none"); + const [statusIndicator, setStatusIndicator] = useState(<>); + const [runButton, setRunButton] = useState(<>); const removeNode = useStore((state) => state.removeNode); // For 'delete node' confirmation popup @@ -40,6 +56,7 @@ export default function NodeLabel({ const [deleteConfirmProps, setDeleteConfirmProps] = useState({ title: "Delete node", message: "Are you sure?", + onConfirm: undefined, }); const stopButton = useMemo( () => ( @@ -153,8 +170,9 @@ export default function NodeLabel({
- {/* */} ); -} +}; + +export default NodeLabel; diff --git a/chainforge/react-server/src/ResponseBoxes.tsx b/chainforge/react-server/src/ResponseBoxes.tsx index 55bb0aa..aedda8f 100644 --- a/chainforge/react-server/src/ResponseBoxes.tsx +++ b/chainforge/react-server/src/ResponseBoxes.tsx @@ -7,7 +7,6 @@ import { StandardizedLLMResponse, TypedDict, } from "./backend/typing"; -import { getLabelForResponse } from "./ResponseRatingToolbar"; // Lazy load the response toolbars const ResponseRatingToolbar = lazy(() => import("./ResponseRatingToolbar.js")); diff --git a/chainforge/react-server/src/StatusIndicatorComponent.js b/chainforge/react-server/src/StatusIndicatorComponent.tsx similarity index 62% rename from chainforge/react-server/src/StatusIndicatorComponent.js rename to chainforge/react-server/src/StatusIndicatorComponent.tsx index 0cf6e0e..47458b7 100644 --- a/chainforge/react-server/src/StatusIndicatorComponent.js +++ b/chainforge/react-server/src/StatusIndicatorComponent.tsx @@ -1,8 +1,20 @@ import React from "react"; -export default function StatusIndicator({ status }) { +export enum Status { + WARNING = "warning", + READY = "ready", + ERROR = "error", + LOADING = "loading", +} +interface StatusIndicatorProps { + status: Status; +} + +export default function StatusIndicator({ + status, +}: StatusIndicatorProps): React.ReactElement { switch (status) { - case "warning": // Display mustard 'warning' icon + case Status.WARNING: // Display mustard 'warning' icon return (
⚠ @@ -12,21 +24,21 @@ export default function StatusIndicator({ status }) {
); - case "ready": // Display green checkmark 'ready' icon + case Status.READY: // Display green checkmark 'ready' icon return (
Responses collected and ready.
); - case "error": // Display red 'error' icon + case Status.ERROR: // Display red 'error' icon return (
Error collecting responses.
); - case "loading": // Display animated 'loading' spinner icon + case Status.LOADING: // Display animated 'loading' spinner icon return (
@@ -36,6 +48,6 @@ export default function StatusIndicator({ status }) {
); default: - return []; + return <>; } } diff --git a/chainforge/react-server/src/backend/backend.ts b/chainforge/react-server/src/backend/backend.ts index 2366ed0..21549bc 100644 --- a/chainforge/react-server/src/backend/backend.ts +++ b/chainforge/react-server/src/backend/backend.ts @@ -1285,7 +1285,8 @@ export async function evalWithLLM( for (const resp_obj of all_evald_responses) { if (!resp_obj.eval_res) continue; for (const score of resp_obj.eval_res.items) { - if (score !== undefined) all_eval_res.add(score.toString().trim().toLowerCase()); + if (score !== undefined) + all_eval_res.add(score.toString().trim().toLowerCase()); } } diff --git a/chainforge/react-server/src/backend/query.ts b/chainforge/react-server/src/backend/query.ts index 6a95f5e..162616e 100644 --- a/chainforge/react-server/src/backend/query.ts +++ b/chainforge/react-server/src/backend/query.ts @@ -169,7 +169,11 @@ export class PromptPipeline { llm_params?: Dict, chat_histories?: ChatHistoryInfo[], should_cancel?: () => boolean, - ): AsyncGenerator { + ): AsyncGenerator< + RawLLMResponseObject | LLMResponseError, + boolean, + undefined + > { // Load any cache'd responses const responses = this._load_cached_responses(); @@ -323,7 +327,7 @@ export class PromptPipeline { [key: string]: RawLLMResponseObject | RawLLMResponseObject[]; } { if (this._storageKey === undefined) return {}; - const data: Record = + const data: Record = StorageCache.get(this._storageKey) ?? {}; // Before retuning, verify data integrity: check that uids are present for all responses. diff --git a/chainforge/react-server/src/backend/typing.ts b/chainforge/react-server/src/backend/typing.ts index d914b11..bcb2dfd 100644 --- a/chainforge/react-server/src/backend/typing.ts +++ b/chainforge/react-server/src/backend/typing.ts @@ -33,7 +33,7 @@ export interface TemplateVarInfo { } export interface PromptVarType { - [key: string]: Array + [key: string]: Array; } /** OpenAI chat message format */ @@ -129,8 +129,17 @@ export interface RawLLMResponseObject extends BaseLLMResponseObject { } export type EvaluationResults = { - items: (boolean | number | string)[], - dtype: "KeyValue" | "KeyValue_Numeric" | "KeyValue_Categorical" | "KeyValue_Mixed" | "Numeric" | "Categorical" | "Mixed" | "Unknown" | "Empty", + items: (boolean | number | string)[]; + dtype: + | "KeyValue" + | "KeyValue_Numeric" + | "KeyValue_Categorical" + | "KeyValue_Mixed" + | "Numeric" + | "Categorical" + | "Mixed" + | "Unknown" + | "Empty"; }; /** A standard response format expected by the front-end. */ @@ -155,13 +164,13 @@ export interface LLMAPICall { /** What LLM to call, at what settings. */ export type LLMSpec = { - name: string, - emoji: string, - base_model: string, - model: string, - temp: number, - key?: string, - formData?: Dict, - settings?: Dict, - progress?: TypedDict, // only used for front-end to display progress collecting responses for this LLM + name: string; + emoji: string; + base_model: string; + model: string; + temp: number; + key?: string; + formData?: Dict; + settings?: Dict; + progress?: TypedDict; // only used for front-end to display progress collecting responses for this LLM }; diff --git a/chainforge/react-server/src/store.tsx b/chainforge/react-server/src/store.tsx index f5c3b2f..4695dc9 100644 --- a/chainforge/react-server/src/store.tsx +++ b/chainforge/react-server/src/store.tsx @@ -1,5 +1,14 @@ import { create } from "zustand"; -import { addEdge, applyNodeChanges, applyEdgeChanges, Edge, Node, NodeChange, EdgeChange, Connection, MarkerType } from "reactflow"; +import { + addEdge, + applyNodeChanges, + applyEdgeChanges, + Edge, + Node, + NodeChange, + EdgeChange, + MarkerType, +} from "reactflow"; import { escapeBraces } from "./backend/template"; import { deepcopy, @@ -213,60 +222,75 @@ export const initLLMProviders = initLLMProviderMenu interface StoreHandles { // Nodes and edges - nodes: Node[], - edges: Edge[], + nodes: Node[]; + edges: Edge[]; // Helper functions for nodes and edges - getNode: (id: string) => Node, - addNode: (newnode: Node) => void, - removeNode: (id: string) => void, - deselectAllNodes: () => void, - bringNodeToFront: (id: string) => void, - duplicateNode: (id: string, offset: undefined | {x?: number, y?: number}) => Node, - setNodes: (newnodes: Node[]) => void, - setEdges: (newedges: Edge[]) => void, - removeEdge: (id: string) => void, - onNodesChange: (changes: NodeChange[]) => void, - onEdgesChange: (changes: EdgeChange[]) => void, - onConnect: (connection: Edge) => void, + getNode: (id: string) => Node; + addNode: (newnode: Node) => void; + removeNode: (id: string) => void; + deselectAllNodes: () => void; + bringNodeToFront: (id: string) => void; + duplicateNode: ( + id: string, + offset: undefined | { x?: number; y?: number }, + ) => Node; + setNodes: (newnodes: Node[]) => void; + setEdges: (newedges: Edge[]) => void; + removeEdge: (id: string) => void; + onNodesChange: (changes: NodeChange[]) => void; + onEdgesChange: (changes: EdgeChange[]) => void; + onConnect: (connection: Edge) => void; // The LLM providers available in the drop-down list - AvailableLLMs: LLMSpec[], - setAvailableLLMs: (specs: LLMSpec[]) => void + AvailableLLMs: LLMSpec[]; + setAvailableLLMs: (specs: LLMSpec[]) => void; // API keys to LLM providers - apiKeys: TypedDict, - setAPIKeys: (apiKeys: TypedDict) => void, + apiKeys: TypedDict; + setAPIKeys: (apiKeys: TypedDict) => void; // Provider for genAI features aiFeaturesProvider: string, setAIFeaturesProvider: (llmProvider: string) => void; // Global flags - flags: TypedDict, - getFlag: (flag: string) => (boolean | string), - setFlag: (flag: string, val: boolean | string) => void, + flags: TypedDict; + getFlag: (flag: string) => boolean | string; + setFlag: (flag: string, val: boolean | string) => void; // The color to represent a specific LLM, to be globally consistent - llmColors: TypedDict, - getColorForLLM: (llm_name: string) => string | undefined, - getColorForLLMAndSetIfNotFound: (llm_name: string) => string, - genUniqueLLMColor: () => string, - setColorForLLM: (llm_name: string, color: string) => void, - resetLLMColors: () => void, + llmColors: TypedDict; + getColorForLLM: (llm_name: string) => string | undefined; + getColorForLLMAndSetIfNotFound: (llm_name: string) => string; + genUniqueLLMColor: () => string; + setColorForLLM: (llm_name: string, color: string) => void; + resetLLMColors: () => void; // Getting inputs and outputs of nodes - inputEdgesForNode: (sourceNodeId: string) => Edge[], - outputEdgesForNode: (sourceNodeId: string) => Edge[], - pingOutputNodes: (sourceNodeId: string) => void, - getImmediateInputNodeTypes: (targetHandles: string[], node_id: string) => string[], + inputEdgesForNode: (sourceNodeId: string) => Edge[]; + outputEdgesForNode: (sourceNodeId: string) => Edge[]; + pingOutputNodes: (sourceNodeId: string) => void; + getImmediateInputNodeTypes: ( + targetHandles: string[], + node_id: string, + ) => string[]; // Set data for a specific node - setDataPropsForNode: (id: string, data_props: TypedDict) => void, + setDataPropsForNode: ( + id: string, + data_props: TypedDict, + ) => void; // Rasterize data output from nodes ("pull" the data out) - output: (sourceNodeId: string, sourceHandleKey: string) => (string | TemplateVarInfo)[] | null, - pullInputData: (_targetHandles: string[], node_id: string) => TypedDict, + output: ( + sourceNodeId: string, + sourceHandleKey: string, + ) => (string | TemplateVarInfo)[] | null; + pullInputData: ( + _targetHandles: string[], + node_id: string, + ) => TypedDict; } // A global store of variables, used for maintaining state