mirror of
https://github.com/ianarawjo/ChainForge.git
synced 2025-03-14 16:26:45 +00:00
Adding and removing LLM list items
This commit is contained in:
parent
ddade145f8
commit
bf72a6f8a8
15
chain-forge/package-lock.json
generated
15
chain-forge/package-lock.json
generated
@ -39,6 +39,7 @@
|
||||
"react-plotly.js": "^2.6.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"styled-components": "^5.3.10",
|
||||
"uuidv4": "^6.2.13",
|
||||
"web-vitals": "^2.1.4",
|
||||
"zustand": "^4.3.7"
|
||||
}
|
||||
@ -5295,6 +5296,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
|
||||
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
|
||||
@ -19990,6 +19996,15 @@
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/uuidv4": {
|
||||
"version": "6.2.13",
|
||||
"resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz",
|
||||
"integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==",
|
||||
"dependencies": {
|
||||
"@types/uuid": "8.3.4",
|
||||
"uuid": "8.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-to-istanbul": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz",
|
||||
|
@ -34,6 +34,7 @@
|
||||
"react-plotly.js": "^2.6.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"styled-components": "^5.3.10",
|
||||
"uuidv4": "^6.2.13",
|
||||
"web-vitals": "^2.1.4",
|
||||
"zustand": "^4.3.7"
|
||||
},
|
||||
|
@ -2,7 +2,7 @@ import { useDisclosure } from '@mantine/hooks';
|
||||
import { Modal, Button, Group } from '@mantine/core';
|
||||
import { IconSettings, IconTrash } from '@tabler/icons-react';
|
||||
|
||||
export default function SettingsButton() {
|
||||
export default function LLMItemButtonGroup( {onClickTrash, onClickSettings} ) {
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
return (
|
||||
@ -12,8 +12,8 @@ export default function SettingsButton() {
|
||||
</Modal>
|
||||
|
||||
<Group position="right" style={{float: 'right', height:'20px'}}>
|
||||
<Button size="xs" variant="light" compact color="red" style={{padding: '0px'}} ><IconTrash size={"95%"} /></Button>
|
||||
<Button size="xs" variant="light" compact onClick={open}>Settings <IconSettings size={"110%"} /></Button>
|
||||
<Button onClick={onClickTrash} size="xs" variant="light" compact color="red" style={{padding: '0px'}} ><IconTrash size={"95%"} /></Button>
|
||||
<Button onClick={onClickSettings} size="xs" variant="light" compact>Settings <IconSettings size={"110%"} /></Button>
|
||||
</Group>
|
||||
</div>
|
||||
);
|
@ -1,11 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||
import ListItem, { DragItem, ListItemClone } from "./ListItemComponent";
|
||||
import LLMListItem, { DragItem, LLMListItemClone } from "./LLMListItem";
|
||||
import { StrictModeDroppable } from './StrictModeDroppable'
|
||||
|
||||
export default function LLMList({llms}) {
|
||||
export default function LLMList({llms, onItemsChange}) {
|
||||
const [items, setItems] = useState(llms);
|
||||
|
||||
const updateItems = useCallback((new_items) => {
|
||||
setItems(new_items);
|
||||
onItemsChange(new_items);
|
||||
}, [onItemsChange]);
|
||||
|
||||
const onDragEnd = (result) => {
|
||||
const { destination, source } = result;
|
||||
if (!destination) return;
|
||||
@ -21,35 +26,44 @@ export default function LLMList({llms}) {
|
||||
setItems(newItems);
|
||||
};
|
||||
|
||||
const removeItem = useCallback((item_key) => {
|
||||
// Double-check that the item we want to remove is in the list of items...
|
||||
if (!items.find(i => i.key === item_key)) {
|
||||
console.error(`Could not remove model from LLM list: Could not find item with key ${item_key}.`);
|
||||
return;
|
||||
}
|
||||
// Remove it
|
||||
updateItems(items.filter(i => i.key !== item_key));
|
||||
}, [items, updateItems]);
|
||||
|
||||
useEffect(() => {
|
||||
// When LLMs list changes, we need to add new items
|
||||
// while preserving the current order of 'items'.
|
||||
// Check for new items and for each, add to end:
|
||||
let new_items = Array.from(items);
|
||||
llms.forEach(item => {
|
||||
if (!items.find(i => i.key === item.key))
|
||||
new_items.push(item);
|
||||
});
|
||||
|
||||
updateItems(new_items);
|
||||
}, [llms, updateItems]);
|
||||
|
||||
return (
|
||||
<div className="list nowheel nodrag">
|
||||
<div className="list nowheel nodrag">
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<StrictModeDroppable
|
||||
droppableId="droppable"
|
||||
droppableId="llm-list-droppable"
|
||||
renderClone={(provided, snapshot, rubric) => (
|
||||
// <DragItem
|
||||
// {...provided.draggableProps}
|
||||
// {...provided.dragHandleProps}
|
||||
// ref={provided.innerRef}
|
||||
// >
|
||||
<ListItemClone
|
||||
provided={provided}
|
||||
snapshot={snapshot}
|
||||
item={items[rubric.source.index]}
|
||||
/>
|
||||
// </DragItem>
|
||||
<LLMListItemClone provided={provided} snapshot={snapshot} item={items[rubric.source.index]} />
|
||||
)}
|
||||
>
|
||||
{(provided) => (
|
||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||
{items.map((item, index) => (
|
||||
<Draggable key={item.model} draggableId={item.model} index={index}>
|
||||
<Draggable key={item.key} draggableId={item.key} index={index}>
|
||||
{(provided, snapshot) => (
|
||||
<ListItem
|
||||
provided={provided}
|
||||
snapshot={snapshot}
|
||||
item={item}
|
||||
/>
|
||||
<LLMListItem provided={provided} snapshot={snapshot} item={item} removeCallback={removeItem} />
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** Thanks to Kabir Haruna: https://codesandbox.io/s/i0rxsj */
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import SettingsButton from "./SettingsButton"
|
||||
import LLMItemButtonGroup from "./LLMItemButtonGroup"
|
||||
|
||||
const CardHeader = styled.div`
|
||||
font-weight: 500;
|
||||
@ -12,18 +12,6 @@ const CardHeader = styled.div`
|
||||
margin-top: 1px;
|
||||
`;
|
||||
|
||||
const Author = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const CardFooter = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const DragItem = styled.div`
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
@ -35,7 +23,7 @@ export const DragItem = styled.div`
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const ListItem = ({ item, provided, snapshot }) => {
|
||||
const LLMListItem = ({ item, provided, snapshot, removeCallback }) => {
|
||||
return (
|
||||
<DragItem
|
||||
ref={provided.innerRef}
|
||||
@ -44,15 +32,15 @@ const ListItem = ({ item, provided, snapshot }) => {
|
||||
{...provided.dragHandleProps}
|
||||
>
|
||||
<div>
|
||||
<CardHeader>{item.emoji} {item.model}</CardHeader>
|
||||
<SettingsButton />
|
||||
<CardHeader>{item.emoji} {item.name}</CardHeader>
|
||||
<LLMItemButtonGroup onClickTrash={() => removeCallback(item.key)} />
|
||||
</div>
|
||||
|
||||
</DragItem>
|
||||
);
|
||||
};
|
||||
|
||||
export const ListItemClone = ({ item, provided, snapshot }) => {
|
||||
export const LLMListItemClone = ({ item, provided, snapshot }) => {
|
||||
return (
|
||||
<DragItem
|
||||
ref={provided.innerRef}
|
||||
@ -61,11 +49,11 @@ export const ListItemClone = ({ item, provided, snapshot }) => {
|
||||
snapshot={snapshot}
|
||||
>
|
||||
<div>
|
||||
<CardHeader>{item.emoji} {item.model}</CardHeader>
|
||||
<SettingsButton />
|
||||
<CardHeader>{item.emoji} {item.name}</CardHeader>
|
||||
<LLMItemButtonGroup />
|
||||
</div>
|
||||
</DragItem>
|
||||
);
|
||||
};
|
||||
|
||||
export default ListItem;
|
||||
export default LLMListItem;
|
@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
||||
import { Handle } from 'react-flow-renderer';
|
||||
import { Menu, Badge, useMantineTheme } from '@mantine/core';
|
||||
import { Menu, Badge } from '@mantine/core';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import useStore from './store';
|
||||
import StatusIndicator from './StatusIndicatorComponent'
|
||||
import NodeLabel from './NodeLabelComponent'
|
||||
@ -9,13 +10,14 @@ import LLMList from './LLMListComponent'
|
||||
import AlertModal from './AlertModal'
|
||||
|
||||
// Available LLMs
|
||||
const llmItems = [
|
||||
{ model: "GPT3.5", emoji: "🙂", temp: 1.0 },
|
||||
{ model: "GPT4", emoji: "🥵", temp: 1.0 },
|
||||
{ model: "Alpaca 7B", emoji: "🦙", temp: 0.5 },
|
||||
{ model: "Claude v1", emoji: "📚", temp: 0.5 },
|
||||
{ model: "Ian Chatbot", emoji: "💩", temp: 0.5 }
|
||||
const allLLMs = [
|
||||
{ name: "GPT3.5", emoji: "🙂", model: "gpt3.5", temp: 1.0 },
|
||||
{ name: "GPT4", emoji: "🥵", model: "gpt4", temp: 1.0 },
|
||||
{ name: "Alpaca 7B", emoji: "🦙", model: "alpaca.7B", temp: 0.5 },
|
||||
{ name: "Claude v1", emoji: "📚", model: "claude.v1", temp: 0.5 },
|
||||
{ name: "Ian Chatbot", emoji: "💩", model: "test", temp: 0.5 }
|
||||
];
|
||||
const initLLMs = [allLLMs[0]];
|
||||
|
||||
// Helper funcs
|
||||
const truncStr = (s, maxLen) => {
|
||||
@ -43,7 +45,6 @@ const bucketResponsesByLLM = (responses) => {
|
||||
};
|
||||
|
||||
const PromptNode = ({ data, id }) => {
|
||||
const theme = useMantineTheme();
|
||||
|
||||
// Get state from the Zustand store:
|
||||
const edges = useStore((state) => state.edges);
|
||||
@ -55,13 +56,36 @@ const PromptNode = ({ data, id }) => {
|
||||
const [templateVars, setTemplateVars] = useState(data.vars || []);
|
||||
const [promptText, setPromptText] = useState(data.prompt);
|
||||
const [promptTextOnLastRun, setPromptTextOnLastRun] = useState(null);
|
||||
const [selectedLLMs, setSelectedLLMs] = useState(['gpt3.5']);
|
||||
const [status, setStatus] = useState('none');
|
||||
const [responsePreviews, setReponsePreviews] = useState([]);
|
||||
const [numGenerations, setNumGenerations] = useState(data.n || 1);
|
||||
|
||||
// For displaying error messages to user
|
||||
const alertModal = useRef(null);
|
||||
|
||||
// Selecting LLM models to prompt
|
||||
const [llmItems, setLLMItems] = useState(initLLMs.map((i, idx) => ({key: uuid(), ...i})));
|
||||
const [llmItemsCurrState, setLLMItemsCurrState] = useState([]);
|
||||
|
||||
const addModel = useCallback((model) => {
|
||||
// Get the item for that model
|
||||
let item = allLLMs.find(llm => llm.model === model);
|
||||
|
||||
if (!item) { // This should never trigger, but in case it does:
|
||||
alertModal.current.trigger(`Could not find model named '${model}' in list of available LLMs.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Give it a uid as a unique key (this is needed for the draggable list to support multiple same-model items; keys must be unique)
|
||||
item = {key: uuid(), ...item};
|
||||
|
||||
// Add model to LLM list (regardless of it's present already or not).
|
||||
setLLMItems(llmItemsCurrState.concat([item]))
|
||||
}, [llmItemsCurrState]);
|
||||
|
||||
const onLLMListItemsChange = useCallback((new_items) => {
|
||||
setLLMItemsCurrState(new_items);
|
||||
}, [setLLMItemsCurrState]);
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setHovered(true);
|
||||
@ -112,7 +136,7 @@ const PromptNode = ({ data, id }) => {
|
||||
console.log('Connected!');
|
||||
|
||||
// Check that there is at least one LLM selected:
|
||||
if (selectedLLMs.length === 0) {
|
||||
if (llmItems.length === 0) {
|
||||
alert('Please select at least one LLM to prompt.')
|
||||
return;
|
||||
}
|
||||
@ -167,7 +191,7 @@ const PromptNode = ({ data, id }) => {
|
||||
headers: {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
|
||||
body: JSON.stringify({
|
||||
id: id,
|
||||
llm: selectedLLMs,
|
||||
llm: llmItems.map(item => item.model),
|
||||
prompt: py_prompt_template,
|
||||
vars: pulled_data,
|
||||
params: {
|
||||
@ -239,22 +263,6 @@ const PromptNode = ({ data, id }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleLLMChecked = (event) => {
|
||||
console.log(event.target.value, event.target.checked);
|
||||
if (event.target.checked) {
|
||||
if (!selectedLLMs.includes(event.target.value)) {
|
||||
// Add the selected LLM to the list:
|
||||
setSelectedLLMs(selectedLLMs.concat([event.target.value]))
|
||||
}
|
||||
} else {
|
||||
if (selectedLLMs.includes(event.target.value)) {
|
||||
// Remove the LLM from the selected list:
|
||||
const removeByIndex = (array, index) => array.filter((_, i) => i !== index);
|
||||
setSelectedLLMs(removeByIndex(selectedLLMs, selectedLLMs.indexOf(event.target.value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleNumGenChange = (event) => {
|
||||
let n = event.target.value;
|
||||
if (!isNaN(n) && n.length > 0 && /^\d+$/.test(n)) {
|
||||
@ -273,10 +281,6 @@ const PromptNode = ({ data, id }) => {
|
||||
? '1px solid #222'
|
||||
: '1px solid #999';
|
||||
|
||||
const selectedModel = (name) => {
|
||||
console.log(name);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="prompt-node"
|
||||
@ -314,7 +318,7 @@ const PromptNode = ({ data, id }) => {
|
||||
<label htmlFor="num-generations" style={{fontSize: '10pt'}}>Num responses per prompt: </label>
|
||||
<input id="num-generations" name="num-generations" type="number" min={1} max={50} defaultValue={data.n || 1} onChange={handleNumGenChange} className="nodrag"></input>
|
||||
</div>
|
||||
<div id="llms-list" className="nowheel" style={{backgroundColor: '#eee', padding: '8px', overflowY: 'auto', maxHeight: '175px'}}>
|
||||
<div id="llms-list" className="nowheel" style={{backgroundColor: '#eee', borderRadius: '4px', padding: '8px', overflowY: 'auto', maxHeight: '175px'}}>
|
||||
<div style={{marginTop: '6px', marginBottom: '6px', marginLeft: '6px', paddingBottom: '4px', textAlign: 'left', fontSize: '10pt', color: '#777'}}>
|
||||
Models to query:
|
||||
<div className="add-llm-model-btn nodrag">
|
||||
@ -327,14 +331,14 @@ const PromptNode = ({ data, id }) => {
|
||||
<button>Add +</button>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
{llmItems.map(item => (<Menu.Item key={item.model} onClick={() => selectedModel(item.model)} icon={item.emoji}>{item.model}</Menu.Item>))}
|
||||
{allLLMs.map(item => (<Menu.Item key={item.model} onClick={() => addModel(item.model)} icon={item.emoji}>{item.name}</Menu.Item>))}
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="nodrag">
|
||||
<LLMList llms={llmItems} />
|
||||
<LLMList llms={llmItems} onItemsChange={onLLMListItemsChange} />
|
||||
{/* <input type="checkbox" id="gpt3.5" name="gpt3.5" value="gpt3.5" defaultChecked={true} onChange={handleLLMChecked} />
|
||||
<label htmlFor="gpt3.5">GPT3.5 </label>
|
||||
<input type="checkbox" id="gpt4" name="gpt4" value="gpt4" defaultChecked={false} onChange={handleLLMChecked} />
|
||||
|
Loading…
x
Reference in New Issue
Block a user