Skip to content

Commit

Permalink
Right-click to Duplicate (v0.2.6.7) (#150)
Browse files Browse the repository at this point in the history
* Auto-change shortname upon model settings edit

* Adding context menu to nodes on right-click

* Add BaseNode and subclass all CF nodes with BaseNode component

* Add BaseNode to CSVNode

* Move HF and Aleph up in LLM list.

* Rebuild react
  • Loading branch information
ianarawjo authored Nov 9, 2023
1 parent 136fe70 commit e456ce6
Show file tree
Hide file tree
Showing 28 changed files with 239 additions and 72 deletions.
12 changes: 6 additions & 6 deletions chainforge/react-server/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"files": {
"main.css": "/static/css/main.60127273.css",
"main.js": "/static/js/main.ee990fc8.js",
"main.css": "/static/css/main.8665fcca.css",
"main.js": "/static/js/main.3027e2a4.js",
"static/js/787.4c72bb55.chunk.js": "/static/js/787.4c72bb55.chunk.js",
"index.html": "/index.html",
"main.60127273.css.map": "/static/css/main.60127273.css.map",
"main.ee990fc8.js.map": "/static/js/main.ee990fc8.js.map",
"main.8665fcca.css.map": "/static/css/main.8665fcca.css.map",
"main.3027e2a4.js.map": "/static/js/main.3027e2a4.js.map",
"787.4c72bb55.chunk.js.map": "/static/js/787.4c72bb55.chunk.js.map"
},
"entrypoints": [
"static/css/main.60127273.css",
"static/js/main.ee990fc8.js"
"static/css/main.8665fcca.css",
"static/js/main.3027e2a4.js"
]
}
2 changes: 1 addition & 1 deletion chainforge/react-server/build/index.html
Original file line number Diff line number Diff line change
@@ -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.ee990fc8.js"></script><link href="/static/css/main.60127273.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.3027e2a4.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>
2 changes: 0 additions & 2 deletions chainforge/react-server/build/static/css/main.60127273.css

This file was deleted.

This file was deleted.

2 changes: 2 additions & 0 deletions chainforge/react-server/build/static/css/main.8665fcca.css

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions chainforge/react-server/src/BaseNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* The base class for every node in ChainForge.
* Used to wrap common behavior like right-click context menu.
*/

import { useCallback, useMemo, useState, useRef } from "react";
import { Menu } from '@mantine/core';
import { IconCopy, IconX } from '@tabler/icons-react';
import AreYouSureModal from "./AreYouSureModal";
import useStore from './store';

export const BaseNode = ({children, classNames, nodeId, style}) => {

const removeNode = useStore((state) => state.removeNode);
const duplicateNode = useStore((state) => state.duplicateNode);

const [contextMenuStyle, setContextMenuStyle] = useState({left: -100, top:0});
const [contextMenuOpened, setContextMenuOpened] = useState(false);

// For 'delete node' confirmation popup
const deleteConfirmModal = useRef(null);

// Class styles for ChainForge nodes
const classes = useMemo(() => {
return "cfnode " + (classNames ?? "");
}, [classNames]);

// Duplicate the node
const handleDuplicateNode = useCallback(() => {
duplicateNode(nodeId, { x: 28, y: 28 });
}, [nodeId, duplicateNode]);

// Remove the node, after user confirmation dialog
const handleRemoveNode = useCallback(() => {
// Open the 'are you sure' modal:
if (deleteConfirmModal && deleteConfirmModal.current)
deleteConfirmModal.current.trigger();
}, [deleteConfirmModal]);

const handleOpenContextMenu = (e) => {
// Ignore all right-clicked elements that aren't divs:
// (for instance, textfields should still have normal right-click)
if (e.target.localName !== "div")
return;

e.preventDefault();
setContextMenuStyle({
dropdown: {
position: 'absolute',
left: e.pageX + 'px !important',
top: e.pageY + 'px !important',
boxShadow: '2px 2px 4px #ccc',
}
});
setContextMenuOpened(true);
};

// A BaseNode is just a div with "cfnode" as a class, and optional other className(s) for the specific node.
// It adds a context menu to all nodes upon right-click of the node itself (the div), to duplicate or delete the node.
return (<div className={classes} onPointerDown={() => setContextMenuOpened(false)} onContextMenu={handleOpenContextMenu} style={style}>
<AreYouSureModal ref={deleteConfirmModal}
title="Delete node"
message="Are you sure you want to delete this node? This action is irreversible."
onConfirm={() => removeNode(nodeId)} />
<Menu opened={contextMenuOpened} withinPortal={true} onChange={setContextMenuOpened} styles={contextMenuStyle}>
{children}
<Menu.Dropdown>
<Menu.Item key='duplicate' onClick={handleDuplicateNode}><IconCopy size='10pt' />&nbsp;Duplicate Node</Menu.Item>
<Menu.Item key='delete' onClick={handleRemoveNode}><IconX size='10pt' />&nbsp;Delete Node</Menu.Item>
</Menu.Dropdown>
</Menu>
</div>);
};

export default BaseNode;
7 changes: 4 additions & 3 deletions chainforge/react-server/src/CommentNode.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import useStore from './store';
import NodeLabel from './NodeLabelComponent'
import NodeLabel from './NodeLabelComponent';
import BaseNode from './BaseNode';
import { Textarea } from '@mantine/core';

/**
Expand All @@ -19,7 +20,7 @@ const CommentNode = ({ data, id }) => {
};

return (
<div className="cfnode" style={{backgroundColor: '#eee'}}>
<BaseNode nodeId={id} style={{backgroundColor: '#eee'}}>
<NodeLabel title={data.title || 'Comment'}
nodeId={id}
icon={'✏️'} />
Expand All @@ -31,7 +32,7 @@ const CommentNode = ({ data, id }) => {
w={'260px'}
minRows={2}
styles={{input: { border: 'none', backgroundColor: '#eee' }}} />
</div>
</BaseNode>
);
};

Expand Down
28 changes: 14 additions & 14 deletions chainforge/react-server/src/CsvNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useStore from './store';
import NodeLabel from './NodeLabelComponent'
import { IconCsv } from '@tabler/icons-react';
import { Handle } from 'reactflow';
import BaseNode from './BaseNode';

const CsvNode = ({ data, id }) => {
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
Expand Down Expand Up @@ -108,20 +109,19 @@ const CsvNode = ({ data, id }) => {
}, [id, data.text]);

return (
<div className="text-fields-node cfnode">
<NodeLabel title={data.title || 'CSV Node'} nodeId={id} icon={<IconCsv size="16px" />} />
{csvInput}
{contentDiv}
{countText ? countText : <></>}
<Handle
type="source"
position="right"
id="output"
className="grouped-handle"
style={{ top: "50%" }}
/>
</div>
);
<BaseNode classNames="text-fields-node" nodeId={id}>
<NodeLabel title={data.title || 'CSV Node'} nodeId={id} icon={<IconCsv size="16px" />} />
{csvInput}
{contentDiv}
{countText ? countText : <></>}
<Handle
type="source"
position="right"
id="output"
className="grouped-handle"
style={{ top: "50%" }}
/>
</BaseNode>);
};

export default CsvNode;
9 changes: 5 additions & 4 deletions chainforge/react-server/src/EvaluatorNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { Button, Code, Modal, Tooltip, Box, Text } from '@mantine/core';
import { Prism } from '@mantine/prism';
import { useDisclosure } from '@mantine/hooks';
import useStore from './store';
import NodeLabel from './NodeLabelComponent'
import { IconTerminal, IconSearch, IconInfoCircle } from '@tabler/icons-react'
import BaseNode from "./BaseNode";
import NodeLabel from './NodeLabelComponent';
import { IconTerminal, IconSearch, IconInfoCircle } from '@tabler/icons-react';
import LLMResponseInspectorModal from './LLMResponseInspectorModal';

// Ace code editor
Expand Down Expand Up @@ -255,7 +256,7 @@ const EvaluatorNode = ({ data, id }) => {
const node_header = data.title || default_header;

return (
<div className="evaluator-node cfnode">
<BaseNode classNames="evaluator-node" nodeId={id}>
<NodeLabel title={node_header}
nodeId={id}
onEdit={hideStatusIndicator}
Expand Down Expand Up @@ -353,7 +354,7 @@ const EvaluatorNode = ({ data, id }) => {
onClick={showResponseInspector}
showNotificationDot={uninspectedResponses} />
) : <></>}
</div>
</BaseNode>
);
};

Expand Down
5 changes: 3 additions & 2 deletions chainforge/react-server/src/InspectorNode.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { Handle } from 'reactflow';
import useStore from './store';
import BaseNode from './BaseNode';
import NodeLabel from './NodeLabelComponent';
import LLMResponseInspector, { exportToExcel } from './LLMResponseInspector';
import fetch_from_backend from './fetch_from_backend';
Expand Down Expand Up @@ -55,7 +56,7 @@ const InspectorNode = ({ data, id }) => {
}, [data, id, handleOnConnect, setDataPropsForNode]);

return (
<div className="inspector-node cfnode">
<BaseNode classNames="inspector-node" nodeId={id}>
<NodeLabel title={data.title || 'Inspect Node'}
nodeId={id}
icon={'🔍'}
Expand All @@ -73,7 +74,7 @@ const InspectorNode = ({ data, id }) => {
style={{ top: "50%" }}
onConnect={handleOnConnect}
/>
</div>
</BaseNode>
);
};

Expand Down
5 changes: 3 additions & 2 deletions chainforge/react-server/src/JoinNode.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect, useCallback } from 'react';
import { Handle } from 'reactflow';
import useStore from './store';
import BaseNode from './BaseNode';
import NodeLabel from './NodeLabelComponent';
import fetch_from_backend from './fetch_from_backend';
import { IconArrowMerge, IconList } from '@tabler/icons-react';
Expand Down Expand Up @@ -332,7 +333,7 @@ const JoinNode = ({ data, id }) => {
}, [data, id, handleOnConnect, setDataPropsForNode]);

return (
<div className="join-node cfnode">
<BaseNode classNames="join-node" nodeId={id}>
<NodeLabel title={data.title || 'Join Node'}
nodeId={id}
icon={<IconArrowMerge size='14pt'/>}
Expand Down Expand Up @@ -389,7 +390,7 @@ const JoinNode = ({ data, id }) => {
className="grouped-handle"
style={{ top: "50%" }}
/>
</div>);
</BaseNode>);
};

export default JoinNode;
5 changes: 3 additions & 2 deletions chainforge/react-server/src/LLMEvalNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Alert, Progress, Textarea } from '@mantine/core';
import { IconAlertTriangle, IconRobot, IconSearch } from "@tabler/icons-react";
import { v4 as uuid } from 'uuid';
import useStore from './store';
import BaseNode from './BaseNode';
import NodeLabel from './NodeLabelComponent';
import fetch_from_backend from './fetch_from_backend';
import { getDefaultModelSettings } from './ModelSettingSchemas';
Expand Down Expand Up @@ -139,7 +140,7 @@ const LLMEvaluatorNode = ({ data, id }) => {
}, [data]);

return (
<div className="evaluator-node cfnode">
<BaseNode classNames="evaluator-node" nodeId={id}>
<NodeLabel title={data.title || 'LLM Scorer'}
nodeId={id}
icon={<IconRobot size="16px" />}
Expand Down Expand Up @@ -200,7 +201,7 @@ const LLMEvaluatorNode = ({ data, id }) => {
onClick={showResponseInspector}
showNotificationDot={uninspectedResponses}
/>) : <></>}
</div>
</BaseNode>
);
};

Expand Down
32 changes: 27 additions & 5 deletions chainforge/react-server/src/ModelSettingSchemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,11 @@ const PaLM2Settings = {
"title": "Model",
"description": "Select a PaLM model to query. For more details on the differences, see the Google PaLM API documentation.",
"enum": ["text-bison-001", "chat-bison-001"],
"default": "chat-bison-001"
"default": "chat-bison-001",
"shortname_map": {
"text-bison-001": "PaLM2-text",
"chat-bison-001": "PaLM2-chat",
}
},
"temperature": {
"type": "number",
Expand Down Expand Up @@ -614,9 +618,19 @@ const HuggingFaceTextInferenceSettings = {
"model": {
"type": "string",
"title": "Model",
"description": "Select a suggested HuggingFace-hosted model to query using the Inference API. For more details, check out https://huggingface.co/inference-api",
"enum": ["mistralai/Mistral-7B-Instruct-v0.1", "HuggingFaceH4/zephyr-7b-beta", "tiiuae/falcon-7b-instruct", "microsoft/DialoGPT-large", "bigscience/bloom-560m", "gpt2", "bigcode/santacoder", "bigcode/starcoder", "Other (HuggingFace)"],
"default": "tiiuae/falcon-7b-instruct",
"description": "Select a suggested HuggingFace-hosted model to query using the Inference API. For more details, check out https://huggingface.co/inference-api",
"enum": ["mistralai/Mistral-7B-Instruct-v0.1", "HuggingFaceH4/zephyr-7b-beta", "tiiuae/falcon-7b-instruct", "microsoft/DialoGPT-large", "bigscience/bloom-560m", "gpt2", "bigcode/santacoder", "bigcode/starcoder", "Other (HuggingFace)"],
"default": "tiiuae/falcon-7b-instruct",
"shortname_map": {
"mistralai/Mistral-7B-Instruct-v0.1": "Mistral-7B",
"HuggingFaceH4/zephyr-7b-beta": "Zephyr-7B",
"tiiuae/falcon-7b-instruct": "Falcon-7B",
"microsoft/DialoGPT-large": "DialoGPT",
"bigscience/bloom-560m": "Bloom560M",
"gpt2": "GPT-2",
"bigcode/santacoder": "santacoder",
"bigcode/starcoder": "starcoder"
}
},
"custom_model": {
"type": "string",
Expand Down Expand Up @@ -769,6 +783,14 @@ const AlephAlphaLuminousSettings = {
"luminous-supreme-control",
],
default: "luminous-base",
shortname_map: {
"luminous-extended": "luminous-ext",
"luminous-extended-control": "luminous-ext-ctrl",
"luminous-base-control": "luminous-base-ctrl",
"luminous-base": "luminous-base",
"luminous-supreme": "luminous-supr",
"luminous-supreme-control": "luminous-supr-ctrl",
}
},
temperature: {
type: "number",
Expand Down Expand Up @@ -1075,7 +1097,7 @@ export const getTemperatureSpecForModel = (modelName) => {
};

export const postProcessFormData = (settingsSpec, formData) => {
// Strip all 'model' and 'shortname' props in the submitted form, as these are passed elsewhere or unecessary for the backend
// Strip all 'model' and 'shortname' props in the submitted form, as these are passed elsewhere or unnecessary for the backend
const skip_keys = {'model': true, 'shortname': true};

let new_data = {};
Expand Down
Loading

0 comments on commit e456ce6

Please sign in to comment.