diff --git a/package-lock.json b/package-lock.json index af98b475dd11746a824d1fa77f691e60a6f2bca1..1fe3af397badfcb4ff58f4434b75e8c413a1717e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,7 @@ "requires": true, "packages": { "": { - "version": "0.10.0", + "version": "0.10.1", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -31,6 +31,7 @@ "@uppy/xhr-upload": "^3.3.2", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", + "@xyflow/react": "^12.4.4", "chokidar": "^4.0.3", "command-exists": "^1.2.9", "dayjs": "^1.11.11", @@ -4879,12 +4880,30 @@ "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", "license": "MIT" }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, "node_modules/@types/d3-format": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.4.5.tgz", "integrity": "sha512-mLxrC1MSWupOSncXN/HOlWUAAIffAEBaI4+PKy2uMPsKe4FNZlk7qrbTjmzJXITQQqBHivaks4Td18azgqnotA==", "license": "MIT" }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, "node_modules/@types/d3-path": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", @@ -4906,6 +4925,12 @@ "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", "license": "MIT" }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, "node_modules/@types/d3-shape": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", @@ -4927,6 +4952,25 @@ "integrity": "sha512-xdDXbpVO74EvadI3UDxjxTdR6QIxm1FKzEA/+F8tL4GWWUg/hgvBqf6chql64U5A9ZUGWo7pEu4eNlyLwbKdhg==", "license": "MIT" }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -6059,6 +6103,36 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@xyflow/react": { + "version": "12.4.4", + "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.4.4.tgz", + "integrity": "sha512-9RZ9dgKZNJOlbrXXST5HPb5TcXPOIDGondjwcjDro44OQRPl1E0ZRPTeWPGaQtVjbg4WpR4BUYwOeshNI2TuVg==", + "license": "MIT", + "dependencies": { + "@xyflow/system": "0.0.52", + "classcat": "^5.0.3", + "zustand": "^4.4.0" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@xyflow/system": { + "version": "0.0.52", + "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.52.tgz", + "integrity": "sha512-pJBMaoh/GEebIABWEIxAai0yf57dm+kH7J/Br+LnLFPuJL87Fhcmm4KFWd/bCUy/kCWUg+2/yFAGY0AUHRPOnQ==", + "license": "MIT", + "dependencies": { + "@types/d3-drag": "^3.0.7", + "@types/d3-selection": "^3.0.10", + "@types/d3-transition": "^3.0.8", + "@types/d3-zoom": "^3.0.8", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0" + } + }, "node_modules/7zip-bin": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", @@ -7777,6 +7851,12 @@ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", "dev": true }, + "node_modules/classcat": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", + "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", + "license": "MIT" + }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", @@ -8794,6 +8874,37 @@ "node": ">=12" } }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-format": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", @@ -8862,6 +8973,15 @@ "node": ">=12" } }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-shape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", @@ -8889,6 +9009,50 @@ "d3-time": "1 - 2" } }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -22871,6 +23035,34 @@ "node": ">= 10" } }, + "node_modules/zustand": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.6.tgz", + "integrity": "sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", @@ -22881,4 +23073,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 66399fd8d15181b3426a6c0eeb4ed39437778153..41ca009b797c3fd5274da281e75adcf9ffcdeb54 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "@uppy/xhr-upload": "^3.3.2", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", + "@xyflow/react": "^12.4.4", "chokidar": "^4.0.3", "command-exists": "^1.2.9", "dayjs": "^1.11.11", @@ -296,4 +297,4 @@ ], "logLevel": "quiet" } -} \ No newline at end of file +} diff --git a/src/renderer/components/Experiment/Eval/EvalJobsTable.tsx b/src/renderer/components/Experiment/Eval/EvalJobsTable.tsx index 1ea12e3a2ca3f7b470cbfb17d618279cbcfcc5f7..d72c74318744419021b23aa1f678c28316ed79b1 100644 --- a/src/renderer/components/Experiment/Eval/EvalJobsTable.tsx +++ b/src/renderer/components/Experiment/Eval/EvalJobsTable.tsx @@ -15,11 +15,11 @@ import { FileDigitIcon, Grid3X3Icon, Trash2Icon, + Type, } from 'lucide-react'; import { useState, useEffect } from 'react'; import useSWR from 'swr'; import * as chatAPI from '../../../lib/transformerlab-api-sdk'; -import dayjs from 'dayjs'; import ViewOutputModalStreaming from './ViewOutputModalStreaming'; import ViewCSVModal from './ViewCSVModal'; import ViewPlotModal from './ViewPlotModal'; @@ -32,8 +32,24 @@ dayjs.extend(relativeTime); var duration = require('dayjs/plugin/duration'); dayjs.extend(duration); +var utc = require('dayjs/plugin/utc'); +var timezone = require('dayjs/plugin/timezone'); // dependent on utc plugin +dayjs.extend(utc); +dayjs.extend(timezone); + const fetcher = (url) => fetch(url).then((res) => res.json()); +function getLocalTimeSinceEvent(utcTimestamp) { + // Parse the UTC timestamp + const eventTime = dayjs.utc(utcTimestamp); + // Convert to local timezone + const localEventTime = eventTime.local(); + // Get current local time + const currentTime = dayjs(); + // Calculate the time difference + return localEventTime.from(currentTime); +} + function RenderScore({ score }) { if (score === undefined) { return <Chip color="warning">Not available</Chip>; @@ -150,24 +166,20 @@ const EvalJobsTable = () => { <tr key={job.id}> <td>{job.id}</td> <td> - {job?.job_data?.plugin} - <br /> - {job?.job_data?.evaluator} + <Typography level="title-md"> + {job?.job_data?.evaluator} + </Typography> + <Typography level="title-sm"> + {job?.job_data?.plugin} + </Typography> + <Typography level="body-sm"> + {getLocalTimeSinceEvent(job?.created_at)} + </Typography> </td> <td> <JobProgress job={job} /> </td> - {/* <td> - Started: - {String(dayjs(job?.created_at).fromNow())} - <br /> - Completed in: - {dayjs - .duration( - dayjs(job?.updated_at).diff(dayjs(job?.created_at)) - ) - .humanize()} - </td> */} + <td> <RenderScore score={job?.job_data?.score} /> {job?.job_data?.additional_output_path && diff --git a/src/renderer/components/Experiment/Workflows/index.tsx b/src/renderer/components/Experiment/Workflows/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..08d848b5cce5fa9765120bf2031635cd5fc58b2c --- /dev/null +++ b/src/renderer/components/Experiment/Workflows/index.tsx @@ -0,0 +1,147 @@ +import { + Box, + Button, + List, + ListItem, + ListItemButton, + ListItemContent, + ListItemDecorator, + Sheet, + Typography, +} from '@mui/joy'; +import { Background, ControlButton, Controls, ReactFlow } from '@xyflow/react'; + +import '@xyflow/react/dist/style.css'; +import { PlayIcon, WorkflowIcon } from 'lucide-react'; +import { useState } from 'react'; + +const initialNodes = [ + { + id: '1', + position: { x: 0, y: 0 }, + data: { label: '1. Generate Synthetic Training Data' }, + }, + { + id: '2', + position: { x: 0, y: 100 }, + data: { label: '2. Evaluate' }, + }, + { + id: '3', + position: { x: 0, y: 200 }, + data: { label: '3. Train on Documents' }, + }, + { + id: '4', + position: { x: 0, y: 300 }, + data: { label: '4. Evaluate' }, + }, +]; +const initialEdges = [ + { + id: 'e1-2', + source: '1', + target: '2', + markerEnd: { type: 'arrow' }, + }, + { + id: 'e2-3', + source: '2', + target: '3', + markerEnd: { type: 'arrow' }, + }, + { + id: 'e3-4', + source: '3', + target: '4', + markerEnd: { + type: 'arrow', + }, + }, +]; + +export default function Workflows({ experimentInfo }) { + const [selectedWorkflow, setSelectedWorkflow] = useState(null); + + return ( + <Sheet + sx={{ + display: 'flex', + flexDirection: 'column', + height: '100%', + overflow: 'hidden', + mb: 3, + }} + > + <Typography level="h1">Workflows</Typography> + <Typography level="body-lg" mb={3}> + This is where it will all go + </Typography> + <Sheet + sx={{ + display: 'flex', + flexDirection: 'row', + gap: 2, + width: '100%', + height: '100%', + }} + > + <Box flex={1}> + <Typography level="title-lg" mb={2}> + Workflows + </Typography> + <List> + {[1, 2, 3].map((i) => ( + <ListItem key={i}> + <ListItemButton onClick={() => setSelectedWorkflow(i)}> + <ListItemDecorator> + <WorkflowIcon /> + </ListItemDecorator> + <ListItemContent>Workflow {i}</ListItemContent> + → + </ListItemButton> + </ListItem> + ))} + </List> + </Box> + <Box flex={3} display="flex" flexDirection="column"> + <Typography level="title-lg" mb={2}> + Workflow {selectedWorkflow} + </Typography> + <Box + sx={{ + display: 'flex', + width: '100%', + height: '100%', + overflow: 'hidden', + flexDirection: 'row', + }} + > + <ReactFlow + nodes={initialNodes} + edges={initialEdges} + fitView + style={{ backgroundColor: '#F7F9FB' }} + > + <Background color="#96ADE9" /> + <Controls> + <ControlButton + onClick={() => { + alert('hi'); + }} + > + a + </ControlButton> + </Controls> + </ReactFlow> + <Box pl={2} display="flex" flexDirection="column" gap={1}> + <Button startDecorator={<PlayIcon />}>Run</Button> + <Button variant="outlined">Edit</Button> + <Button variant="outlined">Fight</Button> + </Box> + </Box> + </Box> + </Sheet> + </Sheet> + ); +} diff --git a/src/renderer/components/MainAppPanel.tsx b/src/renderer/components/MainAppPanel.tsx index fb76d44d49591c10b5a2757661810c8490e17bdb..dfc01ca85a692de1655f0c1c6c9029bb1e4a7324 100644 --- a/src/renderer/components/MainAppPanel.tsx +++ b/src/renderer/components/MainAppPanel.tsx @@ -12,7 +12,7 @@ import PluginDetails from './Plugins/PluginDetails'; import Computer from './Computer'; import Eval from './Experiment/Eval/Eval'; -import Generate from './Experiment/Generate/Generate' +import Generate from './Experiment/Generate/Generate'; import Export from './Experiment/Export/Export'; import Api from './Experiment/Api'; import Settings from './Experiment/Settings'; @@ -29,7 +29,7 @@ import TransformerLabSettings from './TransformerLabSettings'; import Logs from './Logs'; import FoundationHome from './Experiment/Foundation'; import { useState } from 'react'; -import Generate from './Experiment/Generate/Generate'; +import Workflows from './Experiment/Workflows'; // This component renders the main content of the app that is shown // On the rightmost side, regardless of what menu items are selected @@ -178,6 +178,10 @@ export default function MainAppPanel({ /> } /> + <Route + path="/projects/workflows" + element={<Workflows experimentInfo={experimentInfo} />} + /> <Route path="/projects/prompt" element={ diff --git a/src/renderer/components/Nav/Sidebar.tsx b/src/renderer/components/Nav/Sidebar.tsx index 3171b6b5e6b69fb94999298caef684586e9c4d18..d996748ea952b341ac959212d468ebcf2959d155 100644 --- a/src/renderer/components/Nav/Sidebar.tsx +++ b/src/renderer/components/Nav/Sidebar.tsx @@ -26,6 +26,7 @@ import { SquareStackIcon, FileIcon, ChartColumnIncreasingIcon, + WorkflowIcon, } from 'lucide-react'; import { ButtonGroup, IconButton, Sheet, Tooltip } from '@mui/joy'; @@ -133,6 +134,14 @@ export default function Sidebar({ icon={<MessageCircleIcon />} disabled={!experimentInfo?.name || activeModelIsNotSameAsFoundation()} /> + {experimentInfo?.name == 'dev' && ( + <SubNavItem + title="Workflows" + path="/projects/workflows" + icon={<WorkflowIcon />} + disabled={!experimentInfo?.name} + /> + )} {/* <SubNavItem title="Query Docs" path="/projects/rag" diff --git a/src/renderer/components/TransformerLabSettings.tsx b/src/renderer/components/TransformerLabSettings.tsx index 086398b78578f88961dc7e11b52f4bca341272ce..684e87dd79b20c39d7451cf36b68839dc80154fe 100644 --- a/src/renderer/components/TransformerLabSettings.tsx +++ b/src/renderer/components/TransformerLabSettings.tsx @@ -63,6 +63,12 @@ export default function TransformerLabSettings() { /> ); } + const { + data: wandbLoginStatus, + error: wandbLoginStatusError, + isLoading: wandbLoginStatusIsLoading, + mutate: wandbLoginMutate, + } = useSWR(chatAPI.Endpoints.Models.testWandbLogin(), fetcher); return ( <> @@ -132,6 +138,25 @@ export default function TransformerLabSettings() { </FormHelperText> </FormControl> </> + )}{" "} + {wandbLoginStatus?.message === 'OK' ? ( + <Alert color="success">Login to Weights & Biases Successful</Alert> + ) : ( + <FormControl sx={{ maxWidth: '500px', mt: 2 }}> + <FormLabel>Weights & Biases API Key</FormLabel> + <Input name="wandbToken" type="password" /> + <Button + onClick={async () => { + const token = document.getElementsByName('wandbToken')[0].value; + await fetch(chatAPI.Endpoints.Config.Set('WANDB_API_KEY', token)); + await fetch(chatAPI.Endpoints.Models.wandbLogin()); + wandbLoginMutate(); + }} + sx={{ marginTop: 1, width: '100px', alignSelf: 'flex-end' }} + > + Save + </Button> + </FormControl> )} <Divider sx={{ mt: 2, mb: 2 }} /> <Typography level="title-lg" marginBottom={2}> @@ -142,6 +167,8 @@ export default function TransformerLabSettings() { AI Providers and Models </Button> {/* <Divider sx={{ mt: 2, mb: 2 }} /> + )}{' '} + <FormControl sx={{ maxWidth: '500px', mt: 2 }}> <FormLabel>OpenAI API Key</FormLabel> <Input name="openaiKey" type="password" /> diff --git a/src/renderer/lib/transformerlab-api-sdk.ts b/src/renderer/lib/transformerlab-api-sdk.ts index 0bc2ddac6857b240841553ceb2d65547ea1422f5..c89db1941a13ef295be56a8b4a0c62059ddd8953 100644 --- a/src/renderer/lib/transformerlab-api-sdk.ts +++ b/src/renderer/lib/transformerlab-api-sdk.ts @@ -1094,6 +1094,8 @@ Endpoints.Models = { API_URL() + 'model/import_from_local_path?model_path=' + modelPath, HuggingFaceLogin: () => API_URL() + 'model/login_to_huggingface', Delete: (modelId: string) => API_URL() + 'model/delete?model_id=' + modelId, + wandbLogin: () => API_URL() + 'model/login_to_wandb', + testWandbLogin: () => API_URL() + 'model/test_wandb_login', SetOpenAIKey: () => API_URL() + 'model/set_openai_api_key', SetAnthropicKey: () => API_URL() + 'model/set_anthropic_api_key', CheckOpenAIAPIKey: () => API_URL() + 'model/check_openai_api_key',