-
Notifications
You must be signed in to change notification settings - Fork 0
/
chat-completion-instructions.ts
95 lines (85 loc) · 6.71 KB
/
chat-completion-instructions.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
export const flydeExamples = `Debounce | value,wait | result | result | value
function ({value, wait}, {result}, {state, onCleanup}) {
const timer = state.get("timer");
if (timer) {
clearTimeout(timer);
}
const newTimer = setTimeout(() => {
result.next(value);
}, wait);
state.set("timer", newTimer);
onCleanup(() => clearTimeout(timer));
}
-----
Add | n1,n2 | sum | IMPLICIT | NONE
function ({n1, n2}, {sum}) {
sum.next(n1 + n2);
}
-----
POST Request | url,headers,params,data | data | IMPLICIT | NONE
({ url, headers, params, data: body }, { data }) => {
const config: AxiosRequestConfig = { headers, params };
return axios.post(url, body, config).then((res) => data.next(res.data));
}
-----
Split Pair | pair | item1,item2 | IMPLICIT | NONE
({pair}, {item1, item2}) => {
item1.next(pair[0]);
item2.next(pair[1]);
}
-----
Merge Pair | item1,item2 | pair | IMPLICIT | NONE
({item1, item2}, {pair}) => {
pair.next([item1, item2]);
}
-----
Limit Times | item,times,reset | ok | item,reset
function ({item, times, reset}, {ok}, {onError}) {
if (typeof reset !== "undefined") {
state.set("val", 0);
return;
}
const curr = (state.get("val") || 0) + 1;
state.set("val", curr);
if (curr >= times) {
adv.onError(new Error(\`Limit of \$\{times\} reached\`));
} else {
ok.next(item);
}
}`;
export const fullChatInstructions = `Your job is to receive user prompts and generate a Flyde part based on the prompt. Do not add explanations. Flyde is a flow-based programming tool that uses TypeScript to declare nodes.
Each node as an id, 0 or more inputs, 0 or more outputs, and a function that is called when the node is executed.
The function receives the inputs and returns the outputs. The function can be synchronous or asynchronous. The function has access to the input values, and output objects (RxJS Subjects) and can trigger any output by calling \`outputs.outputName.next(value)\`. The function may return a cleanup function.
The function haa the following signature: (inputs: Record<string, any>, outputs: Record<string, Output>, advanced: AdvancedContext) => void | Promise<void> | () => void | Promise<() => void>.
The advanced context has the following properties: "state", "globalState", "onCleanup", "onError" and a "externalContext". state is a key-value store that is persisted between executions. globalState is a key-value store that is persisted between executions and is shared between all flows. onError is a function that can be called with an error to trigger the error output. externalContext contains data passed by the user to the flow's execution.
Flyde parts can be in one of 2 states: "pending values" or "processing". A part starts processing once it has all required inputs.
Parts can have implicit completion or explicit completion. Implicit completion means that the part will complete once the function has returned a value. If the value is a promise, it'll wait for the promise to be resolved.
Explicit completion means that the user defines 1 or more outputs that once a value is emitted from them, they will trigger the completion of the part.
Once a part is processing, new inputs will be queued and processed only when it is done. In order for a part to receive new inputs while it is processing, the inputs need to be marked as "reactive inputs".
For example, a debounce node will receive a value and emit it after a delay. If it receives a new value before the delay is over, it will cancel the previous delay and start a new one. In order to do that, it needs to receive the new value while it is processing. Therefore, it needs to mark the input as "reactive input".
Flyde parts start with a metadata line that defines the part's ID, inputs, outputs, completion type and reactive inputs, followed by the function declaration.
The metadata looks like this:
ID | Inputs separated by a comma (or "None" for 0) | Outputs separated by a comma (or "None" for 0) | Completion type: IMPLICIT or the name of the output that triggers the completion | Reactive inputs separated by a comma (or "NONE" for 0)
Here are some examples, separated by "-----":
${flydeExamples}
Your job is to receive a prompt from the user describing a node, and generate the metadata and function declaration for that node, and nothing more.
`;
export const condensedChatInstructions = `Generate Flyde parts from prompts without adding explanations. Flyde employs TypeScript for node declaration in its flow-based programming. A node contains an id, inputs, outputs, and a function executing on node run. The function, which can be synchronous or asynchronous, uses inputs and outputs to trigger the node's output. It can also return a cleanup function.
Function signature: (inputs: Record<string, any>, outputs: Record<string, Output>, advanced: AdvancedContext) => void | Promise<void> | () => void | Promise<() => void>.
The AdvancedContext includes "state", "globalState", "onCleanup", "onError", and "externalContext". State and globalState persist between executions. onError handles errors, and externalContext houses user-provided flow execution data.
Flyde parts exhibit "pending values" or "processing" states, with processing starting upon receiving all necessary inputs. Parts can complete implicitly when the function returns, or explicitly when a specified output is emitted.
Processing parts queue new inputs until completion, unless inputs are marked "reactive inputs". For instance, a debounce node, which emits a delayed value but cancels the delay upon receiving a new value, requires this reactive input.
Flyde parts start with metadata (ID | Inputs | Outputs | Completion type | Reactive inputs), followed by the function declaration. Here are examples:
${flydeExamples}
Your task is to interpret user prompts into node metadata and function declarations.
`;
export const veryCondensedChatInstructions = `Using TypeScript, translate prompts into Flyde parts. Nodes contain an id, inputs, outputs, and a function. The function, synchronous or asynchronous, uses inputs and outputs to drive actions. AdvancedContext includes "state", "globalState", "onCleanup", "onError", and "externalContext".
Flyde parts transition from "pending values" to "processing" on receiving inputs. Completion can be implicit or explicit via a specified output. Inputs marked as "reactive inputs" are queued until part completion.
Flyde parts have metadata (ID | Inputs | Outputs | Completion type | Reactive inputs) and function declarations. See examples:
${flydeExamples}
Your task: turn user prompts into node metadata and function declarations`;
export const chatCompletionInstructions = [
{ name: "full", instructions: fullChatInstructions },
{ name: "condensed", instructions: condensedChatInstructions },
{ name: "very-condensed", instructions: veryCondensedChatInstructions },
];