Skip to content

Commit

Permalink
[2/n] Disable Run Button: Create runningPromptId field to determine i…
Browse files Browse the repository at this point in the history
…f button should be disabled (#907)

[2n] Disable Run Button: Create runningPromptId field to determine if
button should be disabled



I did a few things:

1. Create a new state id `runningPromptId` to check which prompt is
running, making sure to set these correctly on run prompt actions
2. Read from this state in the AIConfigEditor and passed it as a prop
down to the `RunPromptButton`

Question: Is there a better way of doing step #2 so that we don't need
to keep piping it?

## Test Plan
Make sure that:
1. When you are running a prompt, you can still cancel it
2. When another prompt is running, you can't run any other prompt
3. When prompt is complete (or cancelled or errored), all the prompts
can run again


https://github.com/lastmile-ai/aiconfig/assets/151060367/6e9a9cbf-6469-4ecb-ba74-1ede2ed1a292

---
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with
[ReviewStack](https://reviewstack.dev/lastmile-ai/aiconfig/pull/907).
* __->__ #907
* #905
  • Loading branch information
rossdanlm authored Jan 13, 2024
2 parents c8a2fcb + 623647c commit e47a9b7
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,8 @@ export default function EditorContainer({
return () => clearInterval(interval);
}, [getServerStatusCallback, serverStatus]);

const runningPromptId: string | undefined = aiconfigState._ui.runningPromptId;

return (
<AIConfigContext.Provider value={contextValue}>
<Notifications />
Expand Down Expand Up @@ -907,6 +909,8 @@ export default function EditorContainer({
/>
</div>
{aiconfigState.prompts.map((prompt: ClientPrompt, i: number) => {
const isAnotherPromptRunning =
runningPromptId !== undefined && runningPromptId !== prompt._ui.id;
return (
<Stack key={prompt._ui.id}>
<Flex mt="md">
Expand All @@ -925,6 +929,7 @@ export default function EditorContainer({
onUpdateModelSettings={onUpdatePromptModelSettings}
onUpdateParameters={onUpdatePromptParameters}
defaultConfigModelName={aiconfigState.metadata.default_model}
isRunButtonDisabled={isAnotherPromptRunning}
/>
</Flex>
<div className={classes.addPromptRow}>
Expand Down
81 changes: 57 additions & 24 deletions python/src/aiconfig/editor/client/src/components/aiconfigReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,22 +181,41 @@ function reduceConsolidateAIConfig(
);
}
case "RUN_PROMPT": {
return reduceReplacePrompt(state, action.id, (prompt) => {
const responsePrompt = responseConfig.prompts.find(
(resPrompt) => resPrompt.name === prompt.name
);
// Note: If we are calling "RUN_PROMPT" directly as a dispatched event
// type, we automatically set the state there to `isRunning` for that
// prompt. That logic does not happen here, it happens in
// `aiconfigReducer`.
// If we are calling "RUN_PROMPT" indirectly via the action of a
// "CONSOLIDATE_AICONFIG" dispatch, we end up here. We need to check
// if we actually want to set the prompt state to `isRunning`
const isRunning = action.isRunning ?? false;
const stateWithUpdatedRunningPromptId = {
...state,
_ui: {
...state._ui,
runningPromptId: isRunning ? action.id : undefined,
},
};
return reduceReplacePrompt(
stateWithUpdatedRunningPromptId,
action.id,
(prompt) => {
const responsePrompt = responseConfig.prompts.find(
(resPrompt) => resPrompt.name === prompt.name
);

const outputs = responsePrompt?.outputs ?? prompt.outputs;
const outputs = responsePrompt?.outputs ?? prompt.outputs;

return {
...prompt,
_ui: {
...prompt._ui,
isRunning: action.isRunning ?? false,
},
outputs,
};
});
return {
...prompt,
_ui: {
...prompt._ui,
isRunning,
},
outputs,
};
}
);
}
case "UPDATE_PROMPT_INPUT": {
return reduceReplacePrompt(state, action.id, consolidatePrompt);
Expand Down Expand Up @@ -226,19 +245,19 @@ export default function aiconfigReducer(
const prompts = state.prompts.map((prompt) => {
if (prompt.outputs) {
return {
...prompt,
outputs: undefined
}
...prompt,
outputs: undefined,
};
} else {
return prompt;
}
});


for (const prompt of prompts) {
if (prompt.outputs) {
delete prompt.outputs;
}}
for (const prompt of prompts) {
if (prompt.outputs) {
delete prompt.outputs;
}
}

return {
...dirtyState,
Expand All @@ -254,7 +273,14 @@ export default function aiconfigReducer(
};
}
case "RUN_PROMPT": {
return reduceReplacePrompt(dirtyState, action.id, (prompt) => ({
const runningState = {
...dirtyState,
_ui: {
...dirtyState._ui,
runningPromptId: action.id,
},
};
return reduceReplacePrompt(runningState, action.id, (prompt) => ({
...prompt,
_ui: {
...prompt._ui,
Expand All @@ -264,7 +290,14 @@ export default function aiconfigReducer(
}));
}
case "RUN_PROMPT_ERROR": {
return reduceReplacePrompt(dirtyState, action.id, (prompt) => ({
const nonRunningState = {
...dirtyState,
_ui: {
...dirtyState._ui,
runningPromptId: undefined,
},
};
return reduceReplacePrompt(nonRunningState, action.id, (prompt) => ({
...prompt,
_ui: {
...prompt._ui,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Props = {
newParameters: Record<string, unknown>
) => void;
defaultConfigModelName?: string;
isRunButtonDisabled?: boolean;
};

export default memo(function PromptContainer({
Expand All @@ -43,6 +44,7 @@ export default memo(function PromptContainer({
onUpdateModel,
onUpdateModelSettings,
onUpdateParameters,
isRunButtonDisabled = false,
}: Props) {
const promptId = prompt._ui.id;
const onChangeInput = useCallback(
Expand Down Expand Up @@ -119,6 +121,7 @@ export default memo(function PromptContainer({
onCancelRun={onCancelRun}
onRunPrompt={runPrompt}
isRunning={prompt._ui.isRunning}
isRunButtonDisabled={isRunButtonDisabled}
/>
<PromptOutputBar />
{prompt.outputs && <PromptOutputsRenderer outputs={prompt.outputs} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Props = {
onCancelRun: () => Promise<void>;
onRunPrompt: () => Promise<void>;
isRunning?: boolean;
isRunButtonDisabled?: boolean;
};

type ErrorFallbackProps = {
Expand Down Expand Up @@ -75,6 +76,7 @@ export default memo(function PromptInputRenderer({
onCancelRun,
onRunPrompt,
isRunning = false,
isRunButtonDisabled = false,
}: Props) {
const { classes } = useStyles();

Expand All @@ -93,6 +95,7 @@ export default memo(function PromptInputRenderer({
<div className={classes.promptInputButtonWrapper}>
<RunPromptButton
isRunning={isRunning}
disabled={isRunButtonDisabled}
cancel={onCancelRun}
runPrompt={onRunPrompt}
/>
Expand Down
1 change: 1 addition & 0 deletions python/src/aiconfig/editor/client/src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type ClientAIConfig = Omit<AIConfig, "prompts"> & {
prompts: ClientPrompt[];
_ui: {
isDirty?: boolean;
runningPromptId?: string;
};
};

Expand Down

0 comments on commit e47a9b7

Please sign in to comment.