Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1033/ sync data view in side by side view #1068

Merged
merged 7 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions agenta-web/src/components/ChatInputs/ChatInputs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {ChatMessage, ChatRole} from "@/lib/Types"
import {MinusOutlined, PlusOutlined} from "@ant-design/icons"
import {Button, Input, Select, Space, Tooltip} from "antd"
import {cloneDeep} from "lodash"
import React, {useEffect, useRef, useState} from "react"
import {createUseStyles} from "react-jss"
import {useUpdateEffect} from "usehooks-ts"
Expand Down Expand Up @@ -63,7 +64,7 @@ const ChatInputs: React.FC<Props> = ({
}) => {
const classes = useStyles()
const [messages, setMessages] = useState<ChatMessage[]>(
value || defaultValue || [getDefaultNewMessage()],
cloneDeep(value || defaultValue || [getDefaultNewMessage()]),
)
const onChangeRef = useRef(onChange)

Expand All @@ -77,35 +78,50 @@ const ChatInputs: React.FC<Props> = ({
const newMessages = [...messages]
newMessages[index].role = role
setMessages(newMessages)
if (onChangeRef.current) {
onChangeRef.current(cloneDeep(newMessages))
}
}

const handleInputChange = (index: number, event: React.ChangeEvent<HTMLTextAreaElement>) => {
const {value} = event.target
const newMessages = [...messages]
newMessages[index].content = value
setMessages(newMessages)
if (onChangeRef.current) {
onChangeRef.current(cloneDeep(newMessages))
}
}

const handleDelete = (index: number) => {
setMessages((prev) => prev.filter((_, i) => i !== index))
const newMessages = messages.filter((_, i) => i !== index)
setMessages(newMessages)
if (onChangeRef.current) {
onChangeRef.current(cloneDeep(newMessages))
}
}

const handleAdd = () => {
setMessages((prev) => prev.concat([getDefaultNewMessage()]))
const newMessages = messages.concat([getDefaultNewMessage()])
setMessages(newMessages)
if (onChangeRef.current) {
onChangeRef.current(cloneDeep(newMessages))
}
}

useEffect(() => {
onChangeRef.current = onChange
}, [onChange])

useUpdateEffect(() => {
if (onChangeRef.current) {
onChangeRef.current(messages)
}
}, [messages])
// disabled for now (to be reverted if there are issues after this change)
// useUpdateEffect(() => {
// if (onChangeRef.current) {
// onChangeRef.current(cloneDeep(messages))
// }
// }, [messages])

useUpdateEffect(() => {
if (Array.isArray(value)) setMessages(value)
if (Array.isArray(value)) setMessages(cloneDeep(value))
}, [JSON.stringify(value)])

return (
Expand Down
6 changes: 3 additions & 3 deletions agenta-web/src/components/Playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {DndContext, PointerSensor, useSensor} from "@dnd-kit/core"
import {arrayMove, SortableContext, horizontalListSortingStrategy} from "@dnd-kit/sortable"
import DraggableTabNode from "../DraggableTabNode/DraggableTabNode"
import {useLocalStorage} from "usehooks-ts"
import TestContextProvider from "./TestContextProvider"

const Playground: React.FC = () => {
const router = useRouter()
Expand Down Expand Up @@ -259,8 +260,7 @@ const Playground: React.FC = () => {
return (
<div>
{contextHolder}

<div>
<TestContextProvider>
<div
style={{
display: "flex",
Expand Down Expand Up @@ -359,7 +359,7 @@ const Playground: React.FC = () => {
)}
/>
)}
</div>
</TestContextProvider>

<NewVariantModal
isModalOpen={isModalOpen}
Expand Down
24 changes: 24 additions & 0 deletions agenta-web/src/components/Playground/TestContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import useStateCallback, {DispatchWithCallback} from "@/hooks/useStateCallback"
import {GenericObject} from "@/lib/Types"
import {randString} from "@/lib/helpers/utils"
import React, {PropsWithChildren, SetStateAction, createContext, useState} from "react"

export const TestContext = createContext<{
testList: GenericObject[]
setTestList: React.Dispatch<React.SetStateAction<GenericObject[]>>
isRunning: boolean[]
setIsRunning: DispatchWithCallback<SetStateAction<boolean[]>>
}>({testList: [{}], setTestList: () => {}, isRunning: [], setIsRunning: () => {}})

const TestContextProvider: React.FC<PropsWithChildren> = (props) => {
const [testList, setTestList] = useState<GenericObject[]>([{_id: randString(6)}])
const [isRunning, setIsRunning] = useStateCallback<boolean[]>([])

return (
<TestContext.Provider value={{testList, setTestList, isRunning, setIsRunning}}>
{props.children}
</TestContext.Provider>
)
}

export default TestContextProvider
1 change: 1 addition & 0 deletions agenta-web/src/components/Playground/ViewNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ const ViewNavigation: React.FC<Props> = ({
optParams={optParams}
variant={variant}
isChatVariant={!!isChatVariant}
compareMode={compareMode}
/>
</Col>
</Row>
Expand Down
80 changes: 66 additions & 14 deletions agenta-web/src/components/Playground/Views/TestView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useEffect, useState} from "react"
import React, {useContext, useEffect, useState} from "react"
import {Button, Input, Card, Row, Col, Space, Form} from "antd"
import {CaretRightOutlined, PlusOutlined} from "@ant-design/icons"
import {callVariant} from "@/lib/services/api"
Expand All @@ -15,6 +15,8 @@ import {getDefaultNewMessage} from "@/components/ChatInputs/ChatInputs"
import {v4 as uuidv4} from "uuid"
import {testsetRowToChatMessages} from "@/lib/helpers/testset"
import ParamsForm from "../ParamsForm/ParamsForm"
import {TestContext} from "../TestContextProvider"
import {isEqual} from "lodash"

const {TextArea} = Input
const LOADING_TEXT = "Loading..."
Expand Down Expand Up @@ -88,6 +90,7 @@ interface TestViewProps {
inputParams: Parameter[] | null
optParams: Parameter[] | null
isChatVariant?: boolean
compareMode: boolean
}

interface BoxComponentProps {
Expand All @@ -99,6 +102,7 @@ interface BoxComponentProps {
onAddToTestset: (params: Record<string, string>) => void
onDelete?: () => void
isChatVariant?: boolean
variant: Variant
}

const BoxComponent: React.FC<BoxComponentProps> = ({
Expand All @@ -110,6 +114,7 @@ const BoxComponent: React.FC<BoxComponentProps> = ({
onAddToTestset,
onDelete,
isChatVariant = false,
variant,
}) => {
const classes = useStylesBox()
const loading = result === LOADING_TEXT
Expand Down Expand Up @@ -156,7 +161,7 @@ const BoxComponent: React.FC<BoxComponentProps> = ({
/>
</Row>
<Row className={classes.row2} style={{marginBottom: isChatVariant ? 12 : 0}}>
<Col span={24} className={classes.row2Col}>
<Col span={24} className={classes.row2Col} id={variant.variantId}>
<Button
shape="round"
icon={<PlusOutlined />}
Expand All @@ -173,6 +178,7 @@ const BoxComponent: React.FC<BoxComponentProps> = ({
/>
<Button
data-cy="testview-input-parameters-run-button"
className={`testview-run-button-${testData._id}`}
type="primary"
shape="round"
icon={<CaretRightOutlined />}
Expand All @@ -198,10 +204,22 @@ const BoxComponent: React.FC<BoxComponentProps> = ({
)
}

const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVariant}) => {
const App: React.FC<TestViewProps> = ({
inputParams,
optParams,
variant,
isChatVariant,
compareMode,
}) => {
const router = useRouter()
const appId = router.query.app_id as unknown as string
const [testList, setTestList] = useState<GenericObject[]>([{}])
const {
testList: _testList,
setTestList: _setTestList,
isRunning,
setIsRunning,
} = useContext(TestContext)
const [testList, setTestList] = useState<GenericObject[]>(_testList)
const [resultsList, setResultsList] = useState<string[]>(testList.map(() => ""))
const [params, setParams] = useState<Record<string, string> | null>(null)
const classes = useStylesApp()
Expand All @@ -216,6 +234,10 @@ const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVa
})
}, [testList])

useEffect(() => {
setTestList(_testList)
}, [JSON.stringify(_testList)])

const setResultForIndex = (value: string, index: number) => {
if (isChatVariant) {
setTestList((prevState) =>
Expand Down Expand Up @@ -254,9 +276,27 @@ const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVa

const handleRun = async (index: number) => {
try {
const testItem = testList[index]
if (compareMode && !isRunning[index]) {
setIsRunning(
(prevState) => {
const newState = [...prevState]
newState[index] = true
return newState
},
() => {
document
.querySelectorAll(`.testview-run-button-${testItem._id}`)
.forEach((btn) => {
if (btn.parentElement?.id !== variant.variantId) {
;(btn as HTMLButtonElement).click()
}
})
},
)
}
setResultForIndex(LOADING_TEXT, index)

const testItem = testList[index]
const res = await callVariant(
isChatVariant ? removeKeys(testItem, ["chat"]) : testItem,
inputParams || [],
Expand All @@ -274,6 +314,12 @@ const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVa
"\n---------------------\n\nPlease update your code, and re-serve it using cli and try again.\n\nFor more information please read https://docs.agenta.ai/howto/how-to-debug\n\nIf you believe this is a bug, please create a new issue here: https://github.com/Agenta-AI/agenta/issues/new?title=Issue%20in%20playground",
index,
)
} finally {
setIsRunning((prevState) => {
const newState = [...prevState]
newState[index] = false
return newState
})
}
}

Expand All @@ -287,23 +333,28 @@ const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVa
}

const handleAddRow = () => {
setTestList([...testList, {_id: randString(6)}])
_setTestList([...testList, {_id: randString(6)}])
setResultsList([...resultsList, ""])
}

const handleDeleteRow = (testIndex: number) => {
setTestList((prevTestList) => prevTestList.filter((_, index) => index !== testIndex))
_setTestList((prevTestList) => prevTestList.filter((_, index) => index !== testIndex))
setResultsList((prevResultsList) =>
prevResultsList.filter((_, index) => index !== testIndex),
)
}

const handleInputParamChange = (paramName: string, value: any, index: number) => {
setTestList((prevState) => {
const newState = [...prevState]
newState[index] = {...newState[index], [paramName]: value}
return newState
})
const newState = [...testList]
newState[index] = {...newState[index], [paramName]: value}
setTestList(newState)

if (
!isEqual(_testList[index][paramName], value) &&
!isEqual(testList[index][paramName], value)
) {
_setTestList(newState)
}
}

const onLoadTests = (tests: Record<string, string>[], shouldReplace: boolean) => {
Expand All @@ -313,9 +364,9 @@ const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVa
_id: randString(6),
}))
if (shouldReplace) {
setTestList(testsList)
_setTestList(testsList)
} else {
setTestList((prev) => [...prev, ...testsList])
_setTestList((prev) => [...prev, ...testsList])
}
}

Expand Down Expand Up @@ -355,6 +406,7 @@ const App: React.FC<TestViewProps> = ({inputParams, optParams, variant, isChatVa
onAddToTestset={setParams}
onDelete={testList.length >= 2 ? () => handleDeleteRow(index) : undefined}
isChatVariant={isChatVariant}
variant={variant}
/>
))}
<Button
Expand Down
2 changes: 1 addition & 1 deletion agenta-web/src/hooks/useStateCallback.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {SetStateAction, useCallback, useEffect, useRef, useState} from "react"

type Callback<T> = (value?: T) => void
type DispatchWithCallback<T> = (value: T, callback?: Callback<T>) => void
export type DispatchWithCallback<T> = (value: T, callback?: Callback<T>) => void

/**
* This hook mimcs the setState behaviour of class components. An optional callback can be passed
Expand Down
Loading