Skip to content

Commit 603d8bc

Browse files
committed
added: textAreaPurpose, disableWhenEmpty, placeholder support, placeholder style
1 parent fbad810 commit 603d8bc

7 files changed

Lines changed: 94 additions & 18 deletions

File tree

examples/next-openai/src/app/api/autosuggest/route.ts renamed to examples/next-openai/src/app/api/autosuggestions/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Configuration, OpenAIApi } from "openai-edge";
2-
import { OpenAIStream, StreamingTextResponse } from "ai";
32

43
const config = new Configuration({
54
apiKey: process.env.OPENAI_API_KEY,
@@ -13,7 +12,8 @@ export async function POST(req: Request): Promise<Response> {
1312

1413
const response = await openai.createChatCompletion({
1514
model: "gpt-4",
16-
max_tokens: 500,
15+
// model: "gpt-3.5-turbo-0613",
16+
max_tokens: 250,
1717
messages,
1818
});
1919

examples/next-openai/src/app/components/vacation-notes.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ export function VacationNotes(): JSX.Element {
77

88
return (
99
<CopilotTextarea
10-
className="p-4"
10+
className="px-4 py-4"
1111
value={text}
1212
onChange={(value: string) => setText(value)}
1313
placeholder="What are your plans for your vacation?"
1414
autosuggestionsConfig={{
15+
textareaPurpose: "Notes for my upcoming vacation",
1516
debounceTime: 0.7,
1617
acceptAutosuggestionKey: "Tab",
18+
contextCategories: [],
19+
disableWhenEmpty: true,
1720
}}
1821
/>
1922
);

packages/react-textarea/src/components/copilot-textarea/copilot-textarea.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This example is for an Editor with `ReactEditor` and `HistoryEditor`
22
import { Descendant, Editor } from "slate";
3-
import { Editable, Slate } from "slate-react";
4-
import { useCallback, useEffect, useRef } from "react";
3+
import { Editable, RenderPlaceholderProps, Slate } from "slate-react";
4+
import { useCallback, useEffect, useMemo, useRef } from "react";
55
import { useAutosuggestions } from "../../hooks/use-autosuggestions";
66
import { AutosuggestionState } from "../../types/autosuggestion-state";
77
import { clearAutocompletionsFromEditor } from "../../lib/slatejs-edits/clear-autocompletions";
@@ -13,10 +13,12 @@ import {
1313
AutosuggestionsConfig,
1414
defaultAutosuggestionsConfig,
1515
} from "../../types/autosuggestions-config";
16+
import { makeRenderPlaceholderFunction } from "./render-placeholder";
1617

1718
export interface CopilotTextareaProps {
1819
className?: string;
1920
placeholder?: string;
21+
placeholderStyle?: React.CSSProperties;
2022
value?: string;
2123
onChange?: (value: string) => void;
2224
autosuggestionsConfig: Partial<AutosuggestionsConfig>;
@@ -37,10 +39,12 @@ export function CopilotTextarea(props: CopilotTextareaProps): JSX.Element {
3739

3840
const editor = useCopilotTextareaEditor();
3941
const autosuggestionsFunction = useMakeAutosuggestionFunction(
42+
autosuggestionsConfig.textareaPurpose,
4043
autosuggestionsConfig.apiEndpoint,
4144
autosuggestionsConfig.makeSystemMessage,
42-
autosuggestionsConfig.fewSuggestionsMessages,
43-
autosuggestionsConfig.contextCategories
45+
autosuggestionsConfig.fewShotMessages,
46+
autosuggestionsConfig.contextCategories,
47+
autosuggestionsConfig.disableWhenEmpty
4448
);
4549

4650
const insertText = useCallback(
@@ -53,6 +57,20 @@ export function CopilotTextarea(props: CopilotTextareaProps): JSX.Element {
5357
);
5458

5559
const renderElementMemoized = useCallback(renderElement, []);
60+
const renderPlaceholderMemoized = useMemo(() => {
61+
// For some reason slateJS specifies a top value of 0, which makes for strange styling. We override this here.
62+
const placeholderStyleSlatejsOverrides: React.CSSProperties = {
63+
top: undefined,
64+
};
65+
66+
const placeholderStyleAugmented: React.CSSProperties = {
67+
...placeholderStyleSlatejsOverrides,
68+
...props.placeholderStyle,
69+
};
70+
71+
return makeRenderPlaceholderFunction(placeholderStyleAugmented);
72+
}, [props.placeholderStyle]);
73+
5674
const {
5775
currentAutocompleteSuggestion,
5876
onChangeHandler: onChangeHandlerForAutocomplete,
@@ -87,7 +105,9 @@ export function CopilotTextarea(props: CopilotTextareaProps): JSX.Element {
87105
>
88106
<Editable
89107
className={props.className}
108+
placeholder={props.placeholder}
90109
renderElement={renderElementMemoized}
110+
renderPlaceholder={renderPlaceholderMemoized}
91111
onKeyDown={onKeyDownHandlerForAutocomplete}
92112
/>
93113
</Slate>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { RenderElementProps, RenderPlaceholderProps } from "slate-react";
2+
3+
export type RenderPlaceholderFunction = (
4+
props: RenderPlaceholderProps
5+
) => JSX.Element;
6+
7+
export function makeRenderPlaceholderFunction(
8+
placeholderStyle?: React.CSSProperties
9+
): RenderPlaceholderFunction {
10+
return (props: RenderPlaceholderProps) => {
11+
const { style, ...restAttributes } = props.attributes;
12+
13+
return (
14+
<div
15+
{...restAttributes}
16+
style={{
17+
...style,
18+
...placeholderStyle,
19+
}}
20+
>
21+
{props.children}
22+
</div>
23+
);
24+
};
25+
}

packages/react-textarea/src/hooks/use-make-autosuggestions-function.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useCallback, useState } from "react";
22
import { useContext } from "react";
33
import { CopilotContext } from "@copilotkit/react-core";
44
import { AutosuggestionsBareFunction } from "./use-autosuggestions";
5+
import { MakeSystemMessage } from "../types";
56

67
export interface MinimalChatGPTMessage {
78
role: string;
@@ -15,29 +16,39 @@ export interface MinimalChatGPTMessage {
1516
* It sends a POST request to the API endpoint with the messages array containing the system message, few shot messages, and user messages.
1617
* The function returns the suggestion from the API response.
1718
*
19+
* @param textareaPurpose - The purpose of the textarea. This is included in the system message.
1820
* @param apiEndpoint - The API endpoint to send the autosuggestion request to.
1921
* @param makeSystemMessage - A function that takes in a context string and returns a system message to include in the autosuggestion request.
2022
* @param fewShotMessages - An array of few shot messages to include in the autosuggestion request.
2123
* @param contextCategories - The categories of context strings we want to include. By default, we include the (default) "global" context category.
2224
* @returns A memoized function that sends a request to the specified API endpoint to get an autosuggestion for the user's input.
2325
*/
2426
export function useMakeAutosuggestionFunction(
27+
textareaPurpose: string,
2528
apiEndpoint: string,
26-
makeSystemMessage: (message: string) => string,
29+
makeSystemMessage: MakeSystemMessage,
2730
fewShotMessages: MinimalChatGPTMessage[],
28-
contextCategories: string[] | undefined
31+
contextCategories: string[] | undefined,
32+
disableWhenEmpty: boolean
2933
): AutosuggestionsBareFunction {
3034
const { getContextString } = useContext(CopilotContext);
3135

3236
return useCallback(
3337
async (beforeText: string, afterText: string, abortSignal: AbortSignal) => {
38+
if (disableWhenEmpty && beforeText === "" && afterText === "") {
39+
throw new Error("No text to suggest");
40+
}
41+
3442
const res = await fetch(apiEndpoint, {
3543
method: "POST",
3644
body: JSON.stringify({
3745
messages: [
3846
{
3947
role: "system",
40-
content: makeSystemMessage(getContextString(contextCategories)),
48+
content: makeSystemMessage(
49+
getContextString(contextCategories),
50+
textareaPurpose
51+
),
4152
},
4253
...fewShotMessages,
4354
{
@@ -66,6 +77,7 @@ export function useMakeAutosuggestionFunction(
6677
fewShotMessages,
6778
getContextString,
6879
contextCategories,
80+
textareaPurpose,
6981
]
7082
);
7183
}

packages/react-textarea/src/types/autosuggestions-config.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
import { MinimalChatGPTMessage } from "../hooks/use-make-autosuggestions-function";
22

3+
export type MakeSystemMessage = (
4+
textareaPurpose: string,
5+
contextString: string
6+
) => string;
7+
38
export interface AutosuggestionsConfig {
9+
textareaPurpose: string;
410
debounceTime: number;
511
acceptAutosuggestionKey: string;
612

713
apiEndpoint: string;
8-
makeSystemMessage: (context: string) => string;
9-
fewSuggestionsMessages: MinimalChatGPTMessage[];
1014
contextCategories: string[] | undefined;
15+
makeSystemMessage: MakeSystemMessage;
16+
fewShotMessages: MinimalChatGPTMessage[];
17+
disableWhenEmpty: boolean;
1118
}
1219

13-
export function defaultMakeSystemMessage(contextString: string): string {
20+
export const defaultMakeSystemMessage: MakeSystemMessage = (
21+
textareaPurpose,
22+
contextString
23+
) => {
1424
return `
1525
You are a hyper-competent and versatile writing assistant.
1626
17-
The user is writing some text. It may be a long document, or just a short message.
27+
The user is writing some text. The purpose is: ${textareaPurpose}.
1828
Your job is to help the user write - by guessing what they are going to write next as best as you can, and suggesting it to them.
1929
Only guess a SHORT distance ahead. Usually 1 sentence, or at most 1 paragraph.
2030
@@ -26,14 +36,15 @@ The user will provide both the text before and after the cursor. You should use
2636
<TextBeforeCursor>
2737
<YourSuggestion>
2838
29-
If we need space between the text before and after the cursor, make sure to explicitly add it in the suggestion.
39+
If we need to add a whitespace character to the suggested text, make sure to explicitly add it in.
3040
3141
The following external context is also provided. You may draw on it when appropriate.
3242
\`\`\`
3343
${contextString}
3444
\`\`\`
3545
`;
36-
}
46+
};
47+
3748
export const defaultFewShotMessages: MinimalChatGPTMessage[] = [
3849
{
3950
role: "user",
@@ -70,11 +81,13 @@ export const defaultFewShotMessages: MinimalChatGPTMessage[] = [
7081
},
7182
];
7283
export const defaultAutosuggestionsConfig: AutosuggestionsConfig = {
84+
textareaPurpose: "A generic textbox",
7385
debounceTime: 500,
7486
acceptAutosuggestionKey: "Tab",
7587

7688
apiEndpoint: "api/autosuggestions",
7789
makeSystemMessage: defaultMakeSystemMessage,
78-
fewSuggestionsMessages: defaultFewShotMessages,
90+
fewShotMessages: defaultFewShotMessages,
7991
contextCategories: undefined,
92+
disableWhenEmpty: false,
8093
};
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
export type { AutosuggestionsConfig } from "./autosuggestions-config";
1+
export type {
2+
AutosuggestionsConfig,
3+
MakeSystemMessage,
4+
} from "./autosuggestions-config";

0 commit comments

Comments
 (0)