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

Adds config option to use ENTER to send message #164

Merged
merged 6 commits into from
May 17, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/source/users/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ Once you have set all the necessary keys, click the "back" (left arrow) button i
alt="Screen shot of the initial, blank, chat interface."
class="screenshot" />

To compose a message, type it in the text box at the bottom of the chat interface and press <kbd>SHIFT</kbd>+<kbd>ENTER</kbd> to send. You can press <kbd>ENTER</kbd> to add a new line. Once you have sent a message, you should see a response from Jupyternaut, the Jupyter AI chatbot.
To compose a message, type it in the text box at the bottom of the chat interface and press <kbd>ENTER</kbd> to send it. You can press <kbd>SHIFT</kbd>+<kbd>ENTER</kbd> to add a new line. (These are the default keybindings; you can change them in the chat settings pane.) Once you have sent a message, you should see a response from Jupyternaut, the Jupyter AI chatbot.

<img src="../_static/chat-hello-world.png"
alt='Screen shot of an example "Hello world" message sent to Jupyternaut, who responds with "Hello world, how are you today?"'
Expand All @@ -188,7 +188,7 @@ number of tokens in your request, which may cause your request to cost more mone
Review your model provider's cost policy before making large requests.
:::

After highlighting a portion of your notebook, check "Include selection" in the chat panel, type your message, and press <kbd>SHIFT</kbd>+<kbd>ENTER</kbd> to send your message. Your outgoing message will include your selection.
After highlighting a portion of your notebook, check "Include selection" in the chat panel, type your message, and then send your message. Your outgoing message will include your selection.

<img src="../_static/chat-interface-selection.png"
alt='Screen shot of JupyterLab with Jupyter AI&apos;s chat panel active. A Python function is selected, the user has "What does this code do?" as their prompt, and the user has chosen to include the selection with their message.'
Expand Down
1 change: 1 addition & 0 deletions packages/jupyter-ai/jupyter_ai/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,4 @@ class GlobalConfig(BaseModel):
model_provider_id: Optional[str] = None
embeddings_provider_id: Optional[str] = None
api_keys: Dict[str, str] = {}
send_with_shift_enter: Optional[bool] = None
15 changes: 12 additions & 3 deletions packages/jupyter-ai/src/components/chat-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,28 @@ type ChatInputProps = {
toggleIncludeSelection: () => unknown;
replaceSelection: boolean;
toggleReplaceSelection: () => unknown;
helperText: JSX.Element
sendWithShiftEnter: boolean;
sx?: SxProps<Theme>;
};

export function ChatInput(props: ChatInputProps): JSX.Element {

function handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
if (event.key === 'Enter' && event.shiftKey) {
if (event.key === 'Enter' && (
(props.sendWithShiftEnter && event.shiftKey)
|| (!props.sendWithShiftEnter && !event.shiftKey)
)) {
props.onSend();
event.stopPropagation();
event.preventDefault();
}
}

// Set the helper text based on whether Shift+Enter is used for sending.
const helperText = props.sendWithShiftEnter
? <span>Press <b>Shift</b>+<b>Enter</b> to send message</span>
: <span>Press <b>Shift</b>+<b>Enter</b> to add a new line</span>;

return (
<Box sx={props.sx}>
<Box sx={{ display: 'flex'}}>
Expand Down Expand Up @@ -64,7 +73,7 @@ export function ChatInput(props: ChatInputProps): JSX.Element {
FormHelperTextProps={{
sx: {marginLeft: 'auto', marginRight: 0}
}}
helperText={props.value.length > 2 ? props.helperText : ' '}
helperText={props.value.length > 2 ? helperText : ' '}
/>
</Box>
{props.hasSelection && (
Expand Down
43 changes: 41 additions & 2 deletions packages/jupyter-ai/src/components/chat-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { Box } from '@mui/system';
import {
Alert,
Button,
FormControl,
FormControlLabel,
FormLabel,
MenuItem,
Radio,
RadioGroup,
TextField,
CircularProgress
} from '@mui/material';
Expand Down Expand Up @@ -42,7 +47,8 @@ export function ChatSettings() {
const [inputConfig, setInputConfig] = useState<AiService.Config>({
model_provider_id: null,
embeddings_provider_id: null,
api_keys: {}
api_keys: {},
send_with_shift_enter: null
});

// whether the form is currently saving
Expand Down Expand Up @@ -109,7 +115,8 @@ export function ChatSettings() {
const handleSave = async () => {
const inputConfigCopy: AiService.Config = {
...inputConfig,
api_keys: { ...inputConfig.api_keys }
api_keys: { ...inputConfig.api_keys },
send_with_shift_enter: inputConfig.send_with_shift_enter ?? true
};

// delete any empty api keys
Expand Down Expand Up @@ -256,6 +263,38 @@ export function ChatSettings() {
/>
)
)}
<FormControl>
<FormLabel id="send-radio-buttons-group-label">
When writing a message, press <kbd>Enter</kbd> to:
</FormLabel>
<RadioGroup
aria-labelledby="send-radio-buttons-group-label"
value={
(inputConfig.send_with_shift_enter ?? false) ? 'newline' : 'send'
}
name="send-radio-buttons-group"
onChange={e =>
setInputConfig(inputConfig => {
return ({
...inputConfig,
send_with_shift_enter: (e.target as HTMLInputElement).value === 'newline'
});
})}
>
<FormControlLabel
value="send"
control={<Radio />}
label="Send the message"
/>
<FormControlLabel
value="newline"
control={<Radio />}
label={
<>Start a new line (use <kbd>Shift</kbd>+<kbd>Enter</kbd> to send)</>
}
/>
</RadioGroup>
</FormControl>
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button variant="contained" onClick={handleSave} disabled={saving}>
{saving ? 'Saving...' : 'Save changes'}
Expand Down
10 changes: 4 additions & 6 deletions packages/jupyter-ai/src/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ function ChatBody({ chatHandler, setChatView: chatViewHandler }: ChatBodyProps):
const [replaceSelection, setReplaceSelection] = useState(false);
const [input, setInput] = useState('');
const [selection, replaceSelectionFn] = useSelectionContext();
const [sendWithShiftEnter, setSendWithShiftEnter] = useState(true);

/**
* Effect: fetch history on initial render
* Effect: fetch history and config on initial render
*/
useEffect(() => {
async function fetchHistory() {
Expand All @@ -42,6 +43,7 @@ function ChatBody({ chatHandler, setChatView: chatViewHandler }: ChatBodyProps):
chatHandler.getHistory(),
AiService.getConfig()
]);
setSendWithShiftEnter(config.send_with_shift_enter ?? false);
setMessages(history.messages);
if (!config.model_provider_id) {
setShowWelcomeMessage(true);
Expand Down Expand Up @@ -163,11 +165,7 @@ function ChatBody({ chatHandler, setChatView: chatViewHandler }: ChatBodyProps):
paddingBottom: 0,
borderTop: '1px solid var(--jp-border-color1)'
}}
helperText={
<span>
Press <b>Shift</b> + <b>Enter</b> to submit message
</span>
}
sendWithShiftEnter={sendWithShiftEnter}
/>
</>
);
Expand Down
1 change: 1 addition & 0 deletions packages/jupyter-ai/src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export namespace AiService {
model_provider_id: string | null;
embeddings_provider_id: string | null;
api_keys: Record<string, string>;
send_with_shift_enter: boolean | null;
};

export type GetConfigResponse = Config;
Expand Down