mirror of
https://github.com/ianarawjo/ChainForge.git
synced 2025-03-14 08:16:37 +00:00
Merge branch 'main' of https://github.com/ianarawjo/ChainForge
This commit is contained in:
commit
2e0ff1d317
@ -1,15 +1,15 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.8665fcca.css",
|
||||
"main.js": "/static/js/main.df1a9b08.js",
|
||||
"main.css": "/static/css/main.ff59165b.css",
|
||||
"main.js": "/static/js/main.54b090ad.js",
|
||||
"static/js/787.4c72bb55.chunk.js": "/static/js/787.4c72bb55.chunk.js",
|
||||
"index.html": "/index.html",
|
||||
"main.8665fcca.css.map": "/static/css/main.8665fcca.css.map",
|
||||
"main.df1a9b08.js.map": "/static/js/main.df1a9b08.js.map",
|
||||
"main.ff59165b.css.map": "/static/css/main.ff59165b.css.map",
|
||||
"main.54b090ad.js.map": "/static/js/main.54b090ad.js.map",
|
||||
"787.4c72bb55.chunk.js.map": "/static/js/787.4c72bb55.chunk.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.8665fcca.css",
|
||||
"static/js/main.df1a9b08.js"
|
||||
"static/css/main.ff59165b.css",
|
||||
"static/js/main.54b090ad.js"
|
||||
]
|
||||
}
|
@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><script async src="https://www.googletagmanager.com/gtag/js?id=G-RN3FDBLMCR"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-RN3FDBLMCR")</script><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="A visual programming environment for prompt engineering"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>ChainForge</title><script defer="defer" src="/static/js/main.df1a9b08.js"></script><link href="/static/css/main.8665fcca.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><script async src="https://www.googletagmanager.com/gtag/js?id=G-RN3FDBLMCR"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-RN3FDBLMCR")</script><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="A visual programming environment for prompt engineering"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>ChainForge</title><script defer="defer" src="/static/js/main.54b090ad.js"></script><link href="/static/css/main.ff59165b.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
19
chainforge/react-server/src/CodeEvaluatorNode.js
vendored
19
chainforge/react-server/src/CodeEvaluatorNode.js
vendored
@ -19,6 +19,7 @@ import fetch_from_backend from './fetch_from_backend';
|
||||
import { APP_IS_RUNNING_LOCALLY, stripLLMDetailsFromResponses, toStandardResponseFormat } from './backend/utils';
|
||||
import InspectFooter from './InspectFooter';
|
||||
import { escapeBraces } from './backend/template';
|
||||
import LLMResponseInspectorDrawer from './LLMResponseInspectorDrawer';
|
||||
|
||||
// Whether we are running on localhost or not, and hence whether
|
||||
// we have access to the Flask backend for, e.g., Python code evaluation.
|
||||
@ -124,6 +125,7 @@ const CodeEvaluatorNode = ({ data, id, type: node_type }) => {
|
||||
const pullInputData = useStore((state) => state.pullInputData);
|
||||
const pingOutputNodes = useStore((state) => state.pingOutputNodes);
|
||||
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
|
||||
const bringNodeToFront = useStore((state) => state.bringNodeToFront);
|
||||
const [status, setStatus] = useState('none');
|
||||
const nodes = useStore((state) => state.nodes);
|
||||
|
||||
@ -136,6 +138,7 @@ const CodeEvaluatorNode = ({ data, id, type: node_type }) => {
|
||||
// For a way to inspect responses without having to attach a dedicated node
|
||||
const inspectModal = useRef(null);
|
||||
const [uninspectedResponses, setUninspectedResponses] = useState(false);
|
||||
const [showDrawer, setShowDrawer] = useState(false);
|
||||
|
||||
// The programming language for the editor. Also determines what 'execute'
|
||||
// function will ultimately be called.
|
||||
@ -295,7 +298,7 @@ const CodeEvaluatorNode = ({ data, id, type: node_type }) => {
|
||||
})).flat()
|
||||
});
|
||||
|
||||
if (status !== 'ready')
|
||||
if (status !== 'ready' && !showDrawer)
|
||||
setUninspectedResponses(true);
|
||||
|
||||
setStatus('ready');
|
||||
@ -446,8 +449,18 @@ const CodeEvaluatorNode = ({ data, id, type: node_type }) => {
|
||||
{ lastRunSuccess && lastResponses && lastResponses.length > 0 ?
|
||||
(<InspectFooter label={<>Inspect results <IconSearch size='12pt'/></>}
|
||||
onClick={showResponseInspector}
|
||||
showNotificationDot={uninspectedResponses} />
|
||||
) : <></>}
|
||||
showNotificationDot={uninspectedResponses}
|
||||
isDrawerOpen={showDrawer}
|
||||
showDrawerButton={true}
|
||||
onDrawerClick={() => {
|
||||
setShowDrawer(!showDrawer);
|
||||
setUninspectedResponses(false);
|
||||
bringNodeToFront(id);
|
||||
}}
|
||||
/>) : <></>}
|
||||
|
||||
<LLMResponseInspectorDrawer jsonResponses={lastResponses} showDrawer={showDrawer} />
|
||||
|
||||
</BaseNode>
|
||||
);
|
||||
};
|
||||
|
33
chainforge/react-server/src/InspectFooter.js
vendored
33
chainforge/react-server/src/InspectFooter.js
vendored
@ -1,20 +1,35 @@
|
||||
import { useState } from "react";
|
||||
import { Button } from "@mantine/core";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Button, Tooltip } from "@mantine/core";
|
||||
import { IconSearch, IconSquareArrowLeft, IconSquareArrowRight } from "@tabler/icons-react";
|
||||
|
||||
/**
|
||||
* The footer at the bottom of a node, allowing a user to click it
|
||||
* to inspect responses.
|
||||
*/
|
||||
const InspectFooter = ({ label, onClick, showNotificationDot }) => {
|
||||
const InspectFooter = ({ label, onClick, showNotificationDot, showDrawerButton, onDrawerClick, isDrawerOpen }) => {
|
||||
const [text, setText] = useState(label || (<>Inspect responses <IconSearch size='12pt' /></>));
|
||||
const inspectBtnWidth = useMemo(() => (showDrawerButton ? '84%' : '100%'), [showDrawerButton]);
|
||||
const drawerBtn = useMemo(() => {
|
||||
if (showDrawerButton) return (
|
||||
<Tooltip label={`${isDrawerOpen ? 'Close' : 'Open'} inspector drawer`} position='bottom' withArrow>
|
||||
<Button color='blue' variant='subtle' w='16%' p='0px' onClick={onDrawerClick} style={{borderRadius: '0px', borderLeft: '1px solid #bdf', cursor: 'pointer'}}>
|
||||
{isDrawerOpen ?
|
||||
<IconSquareArrowLeft size='12pt' style={{flexShrink: '0'}} />
|
||||
: <IconSquareArrowRight size='12pt' style={{flexShrink: '0'}} />}
|
||||
</Button>
|
||||
</Tooltip>);
|
||||
else return undefined;
|
||||
}, [showDrawerButton, onDrawerClick, isDrawerOpen]);
|
||||
|
||||
return (
|
||||
<div className="eval-inspect-response-footer nodrag" onClick={onClick} style={{display: 'flex', justifyContent:'center'}}>
|
||||
<Button color='blue' variant='subtle' w='100%' >
|
||||
{text}
|
||||
{ showNotificationDot ? <div className="something-changed-circle"></div> : <></>}
|
||||
</Button>
|
||||
<div className="eval-inspect-response-footer nodrag" style={{display: 'flex', justifyContent:'center'}}>
|
||||
<Tooltip label="Open fullscreen inspector" position='bottom' withArrow>
|
||||
<Button color='blue' variant='subtle' w={inspectBtnWidth} onClick={onClick} >
|
||||
{text}
|
||||
{ showNotificationDot ? <div className="something-changed-circle"></div> : <></>}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{drawerBtn}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
2
chainforge/react-server/src/InspectorNode.js
vendored
2
chainforge/react-server/src/InspectorNode.js
vendored
@ -63,7 +63,7 @@ const InspectorNode = ({ data, id }) => {
|
||||
customButtons={[
|
||||
<button className="custom-button" key="export-data" onClick={() => exportToExcel(jsonResponses)}>Export data</button>
|
||||
]} />
|
||||
<div className='inspect-response-container nowheel nodrag'>
|
||||
<div className='inspect-response-container nowheel nodrag' style={{marginTop: '-8pt'}}>
|
||||
<LLMResponseInspector jsonResponses={jsonResponses} />
|
||||
</div>
|
||||
<Handle
|
||||
|
18
chainforge/react-server/src/LLMEvalNode.js
vendored
18
chainforge/react-server/src/LLMEvalNode.js
vendored
@ -12,6 +12,7 @@ import { LLMListContainer } from './LLMListComponent';
|
||||
import LLMResponseInspectorModal from './LLMResponseInspectorModal';
|
||||
import InspectFooter from './InspectFooter';
|
||||
import { initLLMProviders } from './store';
|
||||
import LLMResponseInspectorDrawer from './LLMResponseInspectorDrawer';
|
||||
|
||||
// The default prompt shown in gray highlights to give people a good example of an evaluation prompt.
|
||||
const PLACEHOLDER_PROMPT = "Respond with 'true' if the text below has a positive sentiment, and 'false' if not. Do not reply with anything else.";
|
||||
@ -32,10 +33,12 @@ const LLMEvaluatorNode = ({ data, id }) => {
|
||||
|
||||
const inspectModal = useRef(null);
|
||||
const [uninspectedResponses, setUninspectedResponses] = useState(false);
|
||||
const [showDrawer, setShowDrawer] = useState(false);
|
||||
|
||||
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
|
||||
const inputEdgesForNode = useStore((state) => state.inputEdgesForNode);
|
||||
const pingOutputNodes = useStore((state) => state.pingOutputNodes);
|
||||
const bringNodeToFront = useStore((state) => state.bringNodeToFront);
|
||||
const apiKeys = useStore((state) => state.apiKeys);
|
||||
|
||||
const [lastResponses, setLastResponses] = useState([]);
|
||||
@ -104,12 +107,13 @@ const LLMEvaluatorNode = ({ data, id }) => {
|
||||
|
||||
console.log(json.responses);
|
||||
setLastResponses(json.responses);
|
||||
setUninspectedResponses(true);
|
||||
if (!showDrawer)
|
||||
setUninspectedResponses(true);
|
||||
setStatus('ready');
|
||||
setProgress(undefined);
|
||||
}).catch(handleError);
|
||||
});
|
||||
}, [inputEdgesForNode, promptText, llmScorers, apiKeys, pingOutputNodes, setStatus, alertModal]);
|
||||
}, [inputEdgesForNode, promptText, llmScorers, apiKeys, pingOutputNodes, setStatus, showDrawer, alertModal]);
|
||||
|
||||
const handlePromptChange = useCallback((event) => {
|
||||
// Store prompt text
|
||||
@ -200,7 +204,17 @@ const LLMEvaluatorNode = ({ data, id }) => {
|
||||
(<InspectFooter label={<>Inspect scores <IconSearch size='12pt'/></>}
|
||||
onClick={showResponseInspector}
|
||||
showNotificationDot={uninspectedResponses}
|
||||
isDrawerOpen={showDrawer}
|
||||
showDrawerButton={true}
|
||||
onDrawerClick={() => {
|
||||
setShowDrawer(!showDrawer);
|
||||
setUninspectedResponses(false);
|
||||
bringNodeToFront(id);
|
||||
}}
|
||||
/>) : <></>}
|
||||
|
||||
<LLMResponseInspectorDrawer jsonResponses={lastResponses} showDrawer={showDrawer} />
|
||||
|
||||
</BaseNode>
|
||||
);
|
||||
};
|
||||
|
119
chainforge/react-server/src/LLMResponseInspector.js
vendored
119
chainforge/react-server/src/LLMResponseInspector.js
vendored
@ -4,8 +4,8 @@
|
||||
* Separated from ReactFlow node UI so that it can
|
||||
* be deployed in multiple locations.
|
||||
*/
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Collapse, Radio, MultiSelect, Group, Table, NativeSelect, Checkbox, Flex } from '@mantine/core';
|
||||
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import { Collapse, Radio, MultiSelect, Group, Table, NativeSelect, Checkbox, Flex, Tabs } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { IconTable, IconLayoutList } from '@tabler/icons-react';
|
||||
import * as XLSX from 'xlsx';
|
||||
@ -339,7 +339,7 @@ const LLMResponseInspector = ({ jsonResponses, wideFormat }) => {
|
||||
);
|
||||
});
|
||||
|
||||
setResponses([(<Table key='table'>
|
||||
setResponses([(<Table key='table' fontSize={wideFormat ? 'sm' : 'xs'}>
|
||||
<thead>
|
||||
<tr>{colnames.map(c => (<th key={c}>{c}</th>))}</tr>
|
||||
</thead>
|
||||
@ -360,14 +360,15 @@ const LLMResponseInspector = ({ jsonResponses, wideFormat }) => {
|
||||
if (varnames.length === 0) {
|
||||
// Base case. Display n response(s) to each single prompt, back-to-back:
|
||||
let fixed_width = 100;
|
||||
if (wideFormat && eatenvars.length > 0) {
|
||||
let side_by_side_resps = wideFormat;
|
||||
if (side_by_side_resps && eatenvars.length > 0) {
|
||||
const num_llms = Array.from(new Set(resps.map(getLLMName))).length;
|
||||
fixed_width = Math.max(20, Math.trunc(100 / num_llms)) - 1; // 20% width is lowest we will go (5 LLM response boxes max)
|
||||
}
|
||||
const resp_boxes = generateResponseBoxes(resps, eatenvars, fixed_width);
|
||||
const className = eatenvars.length > 0 ? "response-group" : "";
|
||||
const boxesClassName = eatenvars.length > 0 ? "response-boxes-wrapper" : "";
|
||||
const flexbox = (wideFormat && fixed_width < 100) ? 'flex' : 'block';
|
||||
const flexbox = (side_by_side_resps && fixed_width < 100) ? 'flex' : 'block';
|
||||
const defaultOpened = !first_opened || eatenvars.length === 0 || eatenvars[eatenvars.length-1] === 'LLM';
|
||||
first_opened = true;
|
||||
leaf_id += 1;
|
||||
@ -436,62 +437,62 @@ const LLMResponseInspector = ({ jsonResponses, wideFormat }) => {
|
||||
setMultiSelectValue(new_val);
|
||||
};
|
||||
|
||||
const sz = useMemo(() =>
|
||||
(wideFormat ? 'sm' : 'xs')
|
||||
, [wideFormat]);
|
||||
|
||||
return (<div style={{height: '100%'}}>
|
||||
|
||||
{wideFormat ?
|
||||
<Radio.Group
|
||||
name="viewFormat"
|
||||
value={viewFormat}
|
||||
onChange={setViewFormat}
|
||||
>
|
||||
<Group mt="0px" mb='xs'>
|
||||
<Radio value="hierarchy" label={<span><IconLayoutList size='10pt' style={{marginBottom: '-1px'}}/> Grouped List</span>} />
|
||||
<Radio value="table" label={<span><IconTable size='10pt' style={{marginBottom: '-1px'}}/> Table</span>} />
|
||||
</Group>
|
||||
</Radio.Group>
|
||||
: <></>}
|
||||
|
||||
{viewFormat === "table" ?
|
||||
<Flex gap='xl' align='end'>
|
||||
<NativeSelect
|
||||
value={tableColVar}
|
||||
onChange={(event) => {
|
||||
setTableColVar(event.currentTarget.value);
|
||||
setUserSelectedTableCol(true);
|
||||
}}
|
||||
data={multiSelectVars}
|
||||
label="Select the main variable to use for columns:"
|
||||
mb="sm"
|
||||
w="80%"
|
||||
/>
|
||||
<Checkbox checked={onlyShowScores}
|
||||
label="Only show scores"
|
||||
onChange={(e) => setOnlyShowScores(e.currentTarget.checked)}
|
||||
mb='md'
|
||||
display={showEvalScoreOptions ? 'inherit' : 'none'} />
|
||||
</Flex>
|
||||
: <></>}
|
||||
|
||||
{wideFormat === false || viewFormat === "hierarchy" ?
|
||||
<Flex gap='xl' align='end'>
|
||||
<MultiSelect ref={multiSelectRef}
|
||||
onChange={handleMultiSelectValueChange}
|
||||
className='nodrag nowheel inspect-multiselect'
|
||||
label="Group responses by (order matters):"
|
||||
data={multiSelectVars}
|
||||
placeholder="Pick vars to group responses, in order of importance"
|
||||
size={wideFormat ? 'sm' : 'xs'}
|
||||
value={multiSelectValue}
|
||||
clearSearchOnChange={true}
|
||||
clearSearchOnBlur={true}
|
||||
w={wideFormat ? '80%' : '100%'} />
|
||||
<Checkbox checked={onlyShowScores}
|
||||
label="Only show scores"
|
||||
onChange={(e) => setOnlyShowScores(e.currentTarget.checked)}
|
||||
mb='xs'
|
||||
display={showEvalScoreOptions ? 'inherit' : 'none'} />
|
||||
</Flex>
|
||||
: <></>}
|
||||
<Tabs value={viewFormat} onTabChange={setViewFormat} styles={{tabLabel: {fontSize: wideFormat ? '12pt' : '9pt' }}}>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="hierarchy"><IconLayoutList size="10pt" style={{marginBottom: wideFormat ? '0px' : '-4px'}}/>{wideFormat ? " Grouped List" : ""}</Tabs.Tab>
|
||||
<Tabs.Tab value="table"><IconTable size="10pt" style={{marginBottom: wideFormat ? '0px' : '-4px'}}/>{wideFormat ? " Table View" : ""}</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="hierarchy" pt="xs">
|
||||
<Flex gap='xl' align='end'>
|
||||
<MultiSelect ref={multiSelectRef}
|
||||
onChange={handleMultiSelectValueChange}
|
||||
className='nodrag nowheel inspect-multiselect'
|
||||
label="Group responses by (order matters):"
|
||||
data={multiSelectVars}
|
||||
placeholder="Pick vars to group responses, in order of importance"
|
||||
size={sz}
|
||||
value={multiSelectValue}
|
||||
clearSearchOnChange={true}
|
||||
clearSearchOnBlur={true}
|
||||
w={wideFormat ? '80%' : '100%'} />
|
||||
<Checkbox checked={onlyShowScores}
|
||||
label="Only show scores"
|
||||
onChange={(e) => setOnlyShowScores(e.currentTarget.checked)}
|
||||
mb='xs'
|
||||
size={sz}
|
||||
display={showEvalScoreOptions ? 'inherit' : 'none'} />
|
||||
</Flex>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="table" pt="xs">
|
||||
<Flex gap='xl' align='end'>
|
||||
<NativeSelect
|
||||
value={tableColVar}
|
||||
onChange={(event) => {
|
||||
setTableColVar(event.currentTarget.value);
|
||||
setUserSelectedTableCol(true);
|
||||
}}
|
||||
data={multiSelectVars}
|
||||
label="Select the main variable to use for columns:"
|
||||
mb="sm"
|
||||
size={sz}
|
||||
w="80%"
|
||||
/>
|
||||
<Checkbox checked={onlyShowScores}
|
||||
label="Only show scores"
|
||||
onChange={(e) => setOnlyShowScores(e.currentTarget.checked)}
|
||||
mb='md'
|
||||
size={sz}
|
||||
display={showEvalScoreOptions ? 'inherit' : 'none'} />
|
||||
</Flex>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
|
||||
<div className="nowheel nodrag">
|
||||
{responses}
|
||||
|
13
chainforge/react-server/src/LLMResponseInspectorDrawer.js
vendored
Normal file
13
chainforge/react-server/src/LLMResponseInspectorDrawer.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
import LLMResponseInspector from "./LLMResponseInspector";
|
||||
|
||||
const LLMResponseInspectorDrawer = ({jsonResponses, showDrawer}) => {
|
||||
return (
|
||||
<div className='inspect-responses-drawer' style={{display: showDrawer ? 'initial' : 'none'}}>
|
||||
<div className='inspect-response-container nowheel nodrag' style={{margin: '0px 10px 10px 12px'}}>
|
||||
<LLMResponseInspector jsonResponses={jsonResponses} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LLMResponseInspectorDrawer;
|
19
chainforge/react-server/src/PromptNode.js
vendored
19
chainforge/react-server/src/PromptNode.js
vendored
@ -14,6 +14,8 @@ import { escapeBraces } from './backend/template';
|
||||
import ChatHistoryView from './ChatHistoryView';
|
||||
import InspectFooter from './InspectFooter';
|
||||
import { countNumLLMs, setsAreEqual, getLLMsInPulledInputData } from './backend/utils';
|
||||
import LLMResponseInspector from './LLMResponseInspector';
|
||||
import LLMResponseInspectorDrawer from './LLMResponseInspectorDrawer';
|
||||
|
||||
const getUniqueLLMMetavarKey = (responses) => {
|
||||
const metakeys = new Set(responses.map(resp_obj => Object.keys(resp_obj.metavars)).flat());
|
||||
@ -84,6 +86,7 @@ const PromptNode = ({ data, id, type: node_type }) => {
|
||||
const getImmediateInputNodeTypes = useStore((state) => state.getImmediateInputNodeTypes);
|
||||
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
|
||||
const pingOutputNodes = useStore((state) => state.pingOutputNodes);
|
||||
const bringNodeToFront = useStore((state) => state.bringNodeToFront);
|
||||
|
||||
// API Keys (set by user in popup GlobalSettingsModal)
|
||||
const apiKeys = useStore((state) => state.apiKeys);
|
||||
@ -107,6 +110,7 @@ const PromptNode = ({ data, id, type: node_type }) => {
|
||||
const inspectModal = useRef(null);
|
||||
const [uninspectedResponses, setUninspectedResponses] = useState(false);
|
||||
const [responsesWillChange, setResponsesWillChange] = useState(false);
|
||||
const [showDrawer, setShowDrawer] = useState(false);
|
||||
|
||||
// For continuing with prior LLMs toggle
|
||||
const [contWithPriorLLMs, setContWithPriorLLMs] = useState(data.contChat !== undefined ? data.contChat : (node_type === 'chat' ? true : false));
|
||||
@ -577,7 +581,7 @@ const PromptNode = ({ data, id, type: node_type }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (responsesWillChange)
|
||||
if (responsesWillChange && !showDrawer)
|
||||
setUninspectedResponses(true);
|
||||
setResponsesWillChange(false);
|
||||
|
||||
@ -775,10 +779,21 @@ const PromptNode = ({ data, id, type: node_type }) => {
|
||||
: <></>}
|
||||
|
||||
{ jsonResponses && jsonResponses.length > 0 && status !== 'loading' ?
|
||||
(<InspectFooter onClick={showResponseInspector} showNotificationDot={uninspectedResponses} />
|
||||
(<InspectFooter onClick={showResponseInspector}
|
||||
showNotificationDot={uninspectedResponses}
|
||||
isDrawerOpen={showDrawer}
|
||||
showDrawerButton={true}
|
||||
onDrawerClick={() => {
|
||||
setShowDrawer(!showDrawer);
|
||||
setUninspectedResponses(false);
|
||||
bringNodeToFront(id);
|
||||
}} />
|
||||
) : <></>
|
||||
}
|
||||
</div>
|
||||
|
||||
<LLMResponseInspectorDrawer jsonResponses={jsonResponses} showDrawer={showDrawer} />
|
||||
|
||||
</BaseNode>
|
||||
);
|
||||
};
|
||||
|
17
chainforge/react-server/src/SimpleEvalNode.js
vendored
17
chainforge/react-server/src/SimpleEvalNode.js
vendored
@ -9,6 +9,7 @@ import LLMResponseInspectorModal from "./LLMResponseInspectorModal";
|
||||
import useStore from "./store";
|
||||
import fetch_from_backend from "./fetch_from_backend";
|
||||
import { stripLLMDetailsFromResponses, toStandardResponseFormat } from "./backend/utils";
|
||||
import LLMResponseInspectorDrawer from "./LLMResponseInspectorDrawer";
|
||||
|
||||
const createJSEvalCodeFor = (responseFormat, operation, value, valueType) => {
|
||||
let responseObj = 'r.text'
|
||||
@ -55,6 +56,7 @@ const SimpleEvalNode = ({data, id}) => {
|
||||
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
|
||||
const pullInputData = useStore((state) => state.pullInputData);
|
||||
const pingOutputNodes = useStore((state) => state.pingOutputNodes);
|
||||
const bringNodeToFront = useStore((state) => state.bringNodeToFront);
|
||||
const [pastInputs, setPastInputs] = useState([]);
|
||||
|
||||
const [status, setStatus] = useState('none');
|
||||
@ -64,6 +66,7 @@ const SimpleEvalNode = ({data, id}) => {
|
||||
const [uninspectedResponses, setUninspectedResponses] = useState(false);
|
||||
const [lastResponses, setLastResponses] = useState([]);
|
||||
const [lastRunSuccess, setLastRunSuccess] = useState(true);
|
||||
const [showDrawer, setShowDrawer] = useState(false);
|
||||
|
||||
const [responseFormat, setResponseFormat] = useState(data.responseFormat || "response");
|
||||
const [operation, setOperation] = useState(data.operation || "contains");
|
||||
@ -149,12 +152,12 @@ const SimpleEvalNode = ({data, id}) => {
|
||||
setLastResponses(stripLLMDetailsFromResponses(json.responses));
|
||||
setLastRunSuccess(true);
|
||||
|
||||
if (status !== 'ready')
|
||||
if (status !== 'ready' && !showDrawer)
|
||||
setUninspectedResponses(true);
|
||||
|
||||
setStatus('ready');
|
||||
}).catch((err) => rejected(err.message));
|
||||
}, [handlePullInputs, pingOutputNodes, setStatus, alertModal, status, varValue, varValueType, responseFormat, textValue, valueFieldDisabled]);
|
||||
}, [handlePullInputs, pingOutputNodes, setStatus, alertModal, status, varValue, varValueType, responseFormat, textValue, showDrawer, valueFieldDisabled]);
|
||||
|
||||
const showResponseInspector = useCallback(() => {
|
||||
if (inspectModal && inspectModal.current && lastResponses) {
|
||||
@ -298,7 +301,17 @@ const SimpleEvalNode = ({data, id}) => {
|
||||
(<InspectFooter label={<>Inspect scores <IconSearch size='12pt'/></>}
|
||||
onClick={showResponseInspector}
|
||||
showNotificationDot={uninspectedResponses}
|
||||
isDrawerOpen={showDrawer}
|
||||
showDrawerButton={true}
|
||||
onDrawerClick={() => {
|
||||
setShowDrawer(!showDrawer);
|
||||
setUninspectedResponses(false);
|
||||
bringNodeToFront(id);
|
||||
}}
|
||||
/>) : <></>}
|
||||
|
||||
<LLMResponseInspectorDrawer jsonResponses={lastResponses} showDrawer={showDrawer} />
|
||||
|
||||
</BaseNode>
|
||||
);
|
||||
};
|
||||
|
8
chainforge/react-server/src/store.js
vendored
8
chainforge/react-server/src/store.js
vendored
@ -309,6 +309,14 @@ const useStore = create((set, get) => ({
|
||||
})
|
||||
});
|
||||
},
|
||||
bringNodeToFront: (id) => {
|
||||
set({
|
||||
nodes: get().nodes.map((n) => {
|
||||
n.selected = n.id === id;
|
||||
return n;
|
||||
})
|
||||
});
|
||||
},
|
||||
duplicateNode: (id, offset) => {
|
||||
const nodes = get().nodes;
|
||||
const node = nodes.find(n => n.id === id);
|
||||
|
@ -289,10 +289,10 @@
|
||||
overflow-y: scroll;
|
||||
min-width: 150px;
|
||||
width: 280px;
|
||||
min-height: 200px;
|
||||
min-height: 270px;
|
||||
height: 200px;
|
||||
max-width: 650px;
|
||||
max-height: 650px;
|
||||
max-width: 1150px;
|
||||
max-height: 750px;
|
||||
resize: both;
|
||||
}
|
||||
.inspect-modal-response-container .response-var-header {
|
||||
@ -341,6 +341,19 @@
|
||||
padding-bottom: 20px;
|
||||
min-width: 160px;
|
||||
border-right: 1px solid #eee;
|
||||
padding-left: 8px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
.inspect-responses-drawer {
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: 12px;
|
||||
background-color: white;
|
||||
border: 1px solid #999;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 2px;
|
||||
box-shadow: 4px 0px 4px 0px rgba(0, 0, 0, 0.1) inset;
|
||||
}
|
||||
.response-group-component-header:hover {
|
||||
color: #05e;
|
||||
@ -433,9 +446,11 @@
|
||||
margin: 4px 3px;
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
white-space: pre-wrap;
|
||||
user-select: text;
|
||||
cursor: text;
|
||||
}
|
||||
.small-response-metrics {
|
||||
font-size: 8pt;
|
||||
font-size: 10pt;
|
||||
font-family: -apple-system, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
@ -501,6 +516,7 @@
|
||||
padding: 2px 0px 1px 0px;
|
||||
margin: 0px 2px 4px 2px;
|
||||
border-radius: 5px;
|
||||
min-width: 120px;
|
||||
/* max-width: 30%; */
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user