-
Notifications
You must be signed in to change notification settings - Fork 5.3k
/
Copy pathgenerate-content.mjs
193 lines (181 loc) · 6.08 KB
/
generate-content.mjs
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import app from "../../google_gemini.app.mjs";
import constants from "../../common/constants.mjs";
import { ConfigurationError } from "@pipedream/platform";
export default {
props: {
app,
model: {
propDefinition: [
app,
"model",
() => ({
filter: ({
description,
supportedGenerationMethods,
}) => ![
"discontinued",
"deprecated",
].some((keyword) => description?.includes(keyword))
&& supportedGenerationMethods?.includes(constants.MODEL_METHODS.GENERATE_CONTENT),
}),
],
},
text: {
propDefinition: [
app,
"text",
],
},
responseFormat: {
propDefinition: [
app,
"responseFormat",
],
},
history: {
type: "string[]",
label: "Conversation History",
description: "Previous messages in the conversation. Each item must be a valid JSON string with `text` and `role` (either `user` or `model`). Example: `{\"text\": \"Hello\", \"role\": \"user\"}`",
optional: true,
},
safetySettings: {
type: "string[]",
label: "Safety Settings",
description: "Configure content filtering for different harm categories. Each item must be a valid JSON string with `category` (one of: `HARASSMENT`, `HATE_SPEECH`, `SEXUALLY_EXPLICIT`, `DANGEROUS`, `CIVIC`) and `threshold` (one of: `BLOCK_NONE`, `BLOCK_ONLY_HIGH`, `BLOCK_MEDIUM_AND_ABOVE`, `BLOCK_LOW_AND_ABOVE`). Example: `{\"category\": \"HARASSMENT\", \"threshold\": \"BLOCK_MEDIUM_AND_ABOVE\"}`",
optional: true,
},
},
methods: {
formatHistoryToContent(history) {
if (typeof(history) === "string") {
try {
history = JSON.parse(history);
} catch (e) {
throw new ConfigurationError(`Invalid JSON in history: ${history}`);
}
}
if (Array.isArray(history) && !history?.length) {
return [];
}
return history.map((itemStr) => {
let item = itemStr;
if (typeof item === "string") {
try {
item = JSON.parse(itemStr);
} catch (e) {
throw new ConfigurationError(`Invalid JSON in history item: ${itemStr}`);
}
}
if (!item.text || !item.role || ![
"user",
"model",
].includes(item.role)) {
throw new ConfigurationError("Each history item must include `text` and `role` (either `user` or `model`)");
}
return {
parts: [
{
text: item.text,
},
],
role: item.role,
};
});
},
formatSafetySettings(safetySettings) {
if (!safetySettings?.length) {
return undefined;
}
return safetySettings.map((settingStr) => {
let setting = settingStr;
if (typeof setting === "string") {
try {
setting = JSON.parse(settingStr);
} catch (e) {
throw new ConfigurationError(`Invalid JSON in safety setting: ${settingStr}`);
}
}
if (!setting.category || !setting.threshold) {
throw new ConfigurationError("Each safety setting must include 'category' and 'threshold'");
}
const category = constants.HARM_CATEGORIES[setting.category];
if (!category) {
throw new ConfigurationError(`Invalid category '${setting.category}'. Must be one of: ${Object.keys(constants.HARM_CATEGORIES).join(", ")}`);
}
if (!constants.BLOCK_THRESHOLDS[setting.threshold]) {
throw new ConfigurationError(`Invalid threshold '${setting.threshold}'. Must be one of: ${Object.keys(constants.BLOCK_THRESHOLDS).join(", ")}`);
}
return {
category,
threshold: setting.threshold,
};
});
},
},
async additionalProps() {
const {
model,
responseFormat,
} = this;
const {
outputTokenLimit,
temperature,
topP,
topK,
maxTemperature,
} = await this.app.getModel({
model,
});
return {
...(responseFormat && {
responseSchema: {
type: "string",
label: "Response Schema",
description: "Define the structure of the JSON response. Must be a valid JSON schema object. Leave empty to let Gemini determine the structure.",
optional: true,
},
}),
...(outputTokenLimit && {
maxOutputTokens: {
type: "integer",
label: "Max Output Tokens",
description: `The maximum number of tokens to generate in the response. Eg. \`${outputTokenLimit}\`.`,
optional: true,
max: outputTokenLimit,
},
}),
...(temperature && {
temperature: {
type: "string",
label: "Temperature",
description: `Controls the randomness of the generated text. Lower values make the text more deterministic, while higher values make it more random. Eg. \`${temperature}\`.${maxTemperature
? ` Where max temperature is \`${maxTemperature}\`.`
: ""}`,
optional: true,
},
}),
...(topP && {
topP: {
type: "string",
label: "Top P",
description: `Controls the diversity of the generated text. Lower values make the text more deterministic, while higher values make it more random. Eg. \`${topP}\`.`,
optional: true,
},
}),
...(topK && {
topK: {
type: "integer",
label: "Top K",
description: `Controls the diversity of the generated text. Lower values make the text more deterministic, while higher values make it more random. Eg. \`${topK}\`.`,
optional: true,
},
}),
stopSequences: {
type: "string[]",
label: "Stop Sequences",
description: "The set of character sequences (up to 5) that will stop output generation. If specified, the API will stop at the first appearance of a `stop_sequence`. The stop sequence will not be included as part of the response.",
optional: true,
},
};
},
};