@aj-archipelago/cortex 1.3.35 → 1.3.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/config/default.example.json +0 -20
- package/config.js +160 -6
- package/lib/pathwayTools.js +79 -1
- package/lib/requestExecutor.js +3 -1
- package/lib/util.js +7 -0
- package/package.json +1 -1
- package/pathways/basePathway.js +2 -0
- package/pathways/call_tools.js +379 -0
- package/pathways/system/entity/memory/shared/sys_memory_helpers.js +1 -1
- package/pathways/system/entity/memory/sys_search_memory.js +2 -2
- package/pathways/system/entity/sys_entity_agent.js +289 -0
- package/pathways/system/entity/sys_generator_memory.js +1 -1
- package/pathways/system/entity/sys_generator_results.js +1 -1
- package/pathways/system/entity/sys_get_entities.js +19 -0
- package/pathways/system/entity/tools/shared/sys_entity_tools.js +150 -0
- package/pathways/system/entity/tools/sys_tool_bing_search.js +147 -0
- package/pathways/system/entity/tools/sys_tool_callmodel.js +62 -0
- package/pathways/system/entity/tools/sys_tool_coding.js +53 -0
- package/pathways/system/entity/tools/sys_tool_codingagent.js +100 -0
- package/pathways/system/entity/tools/sys_tool_cognitive_search.js +231 -0
- package/pathways/system/entity/tools/sys_tool_image.js +57 -0
- package/pathways/system/entity/tools/sys_tool_readfile.js +119 -0
- package/pathways/system/entity/tools/sys_tool_reasoning.js +75 -0
- package/pathways/system/entity/tools/sys_tool_remember.js +59 -0
- package/pathways/vision.js +1 -1
- package/server/modelExecutor.js +4 -12
- package/server/pathwayResolver.js +53 -40
- package/server/plugins/azureBingPlugin.js +42 -4
- package/server/plugins/azureCognitivePlugin.js +40 -12
- package/server/plugins/claude3VertexPlugin.js +67 -18
- package/server/plugins/modelPlugin.js +3 -2
- package/server/plugins/openAiReasoningPlugin.js +3 -3
- package/server/plugins/openAiReasoningVisionPlugin.js +48 -0
- package/server/plugins/openAiVisionPlugin.js +192 -7
- package/tests/agentic.test.js +256 -0
- package/tests/call_tools.test.js +216 -0
- package/tests/claude3VertexToolConversion.test.js +78 -0
- package/tests/mocks.js +11 -3
- package/tests/multimodal_conversion.test.js +1 -1
- package/tests/openAiToolPlugin.test.js +242 -0
- package/pathways/test_palm_chat.js +0 -31
- package/server/plugins/palmChatPlugin.js +0 -233
- package/server/plugins/palmCodeCompletionPlugin.js +0 -45
- package/server/plugins/palmCompletionPlugin.js +0 -135
- package/tests/palmChatPlugin.test.js +0 -219
- package/tests/palmCompletionPlugin.test.js +0 -58
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
// palmChatPlugin.js
|
|
2
|
-
import ModelPlugin from './modelPlugin.js';
|
|
3
|
-
import HandleBars from '../../lib/handleBars.js';
|
|
4
|
-
import logger from '../../lib/logger.js';
|
|
5
|
-
|
|
6
|
-
class PalmChatPlugin extends ModelPlugin {
|
|
7
|
-
constructor(pathway, model) {
|
|
8
|
-
super(pathway, model);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Convert to PaLM messages array format if necessary
|
|
12
|
-
convertMessagesToPalm(messages) {
|
|
13
|
-
let context = '';
|
|
14
|
-
let modifiedMessages = [];
|
|
15
|
-
let lastAuthor = '';
|
|
16
|
-
|
|
17
|
-
// remove any empty messages
|
|
18
|
-
messages = messages.filter(message => message.content);
|
|
19
|
-
|
|
20
|
-
messages.forEach(message => {
|
|
21
|
-
const { role, author, content } = message;
|
|
22
|
-
|
|
23
|
-
// Extract system messages into the context string
|
|
24
|
-
if (role === 'system') {
|
|
25
|
-
context += (context.length > 0 ? '\n' : '') + content;
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Aggregate consecutive author messages, appending the content
|
|
30
|
-
if ((role === lastAuthor || author === lastAuthor) && modifiedMessages.length > 0) {
|
|
31
|
-
modifiedMessages[modifiedMessages.length - 1].content += '\n' + content;
|
|
32
|
-
}
|
|
33
|
-
// Only push messages with role 'user' or 'assistant' or existing author messages
|
|
34
|
-
else if (role === 'user' || role === 'assistant' || author) {
|
|
35
|
-
modifiedMessages.push({
|
|
36
|
-
author: author || role,
|
|
37
|
-
content,
|
|
38
|
-
});
|
|
39
|
-
lastAuthor = author || role;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
modifiedMessages,
|
|
45
|
-
context,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Handlebars compiler for context (PaLM chat specific)
|
|
50
|
-
getCompiledContext(text, parameters, context) {
|
|
51
|
-
const combinedParameters = { ...this.promptParameters, ...parameters };
|
|
52
|
-
return context ? HandleBars.compile(context)({ ...combinedParameters, text}) : '';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Handlebars compiler for examples (PaLM chat specific)
|
|
56
|
-
getCompiledExamples(text, parameters, examples = []) {
|
|
57
|
-
const combinedParameters = { ...this.promptParameters, ...parameters };
|
|
58
|
-
|
|
59
|
-
const compileContent = (content) => {
|
|
60
|
-
const compile = HandleBars.compile(content);
|
|
61
|
-
return compile({ ...combinedParameters, text });
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const processExample = (example, key) => {
|
|
65
|
-
if (example[key]?.content) {
|
|
66
|
-
return { ...example[key], content: compileContent(example[key].content) };
|
|
67
|
-
}
|
|
68
|
-
return { ...example[key] };
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
return examples.map((example) => ({
|
|
72
|
-
input: example.input ? processExample(example, 'input') : undefined,
|
|
73
|
-
output: example.output ? processExample(example, 'output') : undefined,
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Set up parameters specific to the PaLM Chat API
|
|
78
|
-
getRequestParameters(text, parameters, prompt) {
|
|
79
|
-
const { modelPromptText, modelPromptMessages, tokenLength } = this.getCompiledPrompt(text, parameters, prompt);
|
|
80
|
-
|
|
81
|
-
// Define the model's max token length
|
|
82
|
-
const modelTargetTokenLength = this.getModelMaxPromptTokens();
|
|
83
|
-
|
|
84
|
-
const palmMessages = this.convertMessagesToPalm(modelPromptMessages || [{ "author": "user", "content": modelPromptText }]);
|
|
85
|
-
|
|
86
|
-
let requestMessages = palmMessages.modifiedMessages;
|
|
87
|
-
|
|
88
|
-
// Check if the token length exceeds the model's max token length
|
|
89
|
-
if (tokenLength > modelTargetTokenLength) {
|
|
90
|
-
// Remove older messages until the token length is within the model's limit
|
|
91
|
-
requestMessages = this.truncateMessagesToTargetLength(requestMessages, modelTargetTokenLength);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const context = this.getCompiledContext(text, parameters, prompt.context || palmMessages.context || '');
|
|
95
|
-
const examples = this.getCompiledExamples(text, parameters, prompt.examples || []);
|
|
96
|
-
|
|
97
|
-
const max_tokens = this.getModelMaxReturnTokens();
|
|
98
|
-
|
|
99
|
-
if (max_tokens < 0) {
|
|
100
|
-
throw new Error(`Prompt is too long to successfully call the model at ${tokenLength} tokens. The model will not be called.`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Ensure there are an odd number of messages for turn taking
|
|
104
|
-
if (requestMessages.length % 2 === 0) {
|
|
105
|
-
requestMessages = requestMessages.slice(1);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const requestParameters = {
|
|
109
|
-
instances: [{
|
|
110
|
-
context: context,
|
|
111
|
-
examples: examples,
|
|
112
|
-
messages: requestMessages,
|
|
113
|
-
}],
|
|
114
|
-
parameters: {
|
|
115
|
-
temperature: this.temperature ?? 0.7,
|
|
116
|
-
maxOutputTokens: max_tokens,
|
|
117
|
-
topP: parameters.topP ?? 0.95,
|
|
118
|
-
topK: parameters.topK ?? 40,
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
return requestParameters;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Get the safetyAttributes from the PaLM Chat API response data
|
|
126
|
-
getSafetyAttributes(data) {
|
|
127
|
-
const { predictions } = data;
|
|
128
|
-
if (!predictions || !predictions.length) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// if we got a predictions array back with more than one prediction, return the safetyAttributes of the first prediction
|
|
133
|
-
if (predictions.length > 1) {
|
|
134
|
-
return predictions[0].safetyAttributes ?? null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// otherwise, return the safetyAttributes of the content of the first prediction
|
|
138
|
-
return predictions[0].safetyAttributes ?? null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Execute the request to the PaLM Chat API
|
|
142
|
-
async execute(text, parameters, prompt, cortexRequest) {
|
|
143
|
-
const requestParameters = this.getRequestParameters(text, parameters, prompt);
|
|
144
|
-
|
|
145
|
-
cortexRequest.data = { ...(cortexRequest.data || {}), ...requestParameters };
|
|
146
|
-
cortexRequest.params = {}; // query params
|
|
147
|
-
|
|
148
|
-
const gcpAuthTokenHelper = this.config.get('gcpAuthTokenHelper');
|
|
149
|
-
const authToken = await gcpAuthTokenHelper.getAccessToken();
|
|
150
|
-
cortexRequest.auth.Authorization = `Bearer ${authToken}`;
|
|
151
|
-
|
|
152
|
-
return this.executeRequest(cortexRequest);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Parse the response from the PaLM Chat API
|
|
156
|
-
parseResponse(data) {
|
|
157
|
-
const { predictions } = data;
|
|
158
|
-
if (!predictions || !predictions.length) {
|
|
159
|
-
return data;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Get the candidates array from the first prediction
|
|
163
|
-
const { candidates } = predictions[0];
|
|
164
|
-
|
|
165
|
-
// if it was blocked, return the blocked message
|
|
166
|
-
if (predictions[0].safetyAttributes?.blocked) {
|
|
167
|
-
return 'The response is blocked because the input or response potentially violates Google policies. Try rephrasing the prompt or adjusting the parameter settings. Currently, only English is supported.';
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (!candidates || !candidates.length) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// If we got a candidates array back with more than one candidate, return the whole array
|
|
175
|
-
if (candidates.length > 1) {
|
|
176
|
-
return candidates;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Otherwise, return the content of the first candidate
|
|
180
|
-
const messageResult = candidates[0].content && candidates[0].content.trim();
|
|
181
|
-
return messageResult ?? null;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Override the logging function to display the messages and responses
|
|
185
|
-
logRequestData(data, responseData, prompt) {
|
|
186
|
-
const instances = data && data.instances;
|
|
187
|
-
const messages = instances && instances[0] && instances[0].messages;
|
|
188
|
-
const { context, examples } = instances && instances [0] || {};
|
|
189
|
-
|
|
190
|
-
if (context) {
|
|
191
|
-
const { length, units } = this.getLength(context);
|
|
192
|
-
logger.info(`[chat request contains context information of length ${length} ${units}]`)
|
|
193
|
-
logger.verbose(`context: ${context}`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (examples && examples.length) {
|
|
197
|
-
logger.info(`[chat request contains ${examples.length} examples]`);
|
|
198
|
-
examples.forEach((example, index) => {
|
|
199
|
-
logger.verbose(`example ${index + 1}: input: "${example.input.content}", output: "${example.output.content}"`);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (messages && messages.length > 1) {
|
|
204
|
-
logger.info(`[chat request contains ${messages.length} messages]`);
|
|
205
|
-
messages.forEach((message, index) => {
|
|
206
|
-
const words = message.content.split(" ");
|
|
207
|
-
const { length, units } = this.getLength(message.content);
|
|
208
|
-
const preview = words.length < 41 ? message.content : words.slice(0, 20).join(" ") + " ... " + words.slice(-20).join(" ");
|
|
209
|
-
|
|
210
|
-
logger.verbose(`message ${index + 1}: author: ${message.author}, ${units}: ${length}, content: "${preview}"`);
|
|
211
|
-
});
|
|
212
|
-
} else if (messages && messages.length === 1) {
|
|
213
|
-
logger.verbose(`${messages[0].content}`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const safetyAttributes = this.getSafetyAttributes(responseData);
|
|
217
|
-
|
|
218
|
-
const responseText = this.parseResponse(responseData);
|
|
219
|
-
const { length, units } = this.getLength(responseText);
|
|
220
|
-
logger.info(`[response received containing ${length} ${units}]`);
|
|
221
|
-
logger.verbose(`${responseText}`);
|
|
222
|
-
|
|
223
|
-
if (safetyAttributes) {
|
|
224
|
-
logger.warn(`[response contains safety attributes: ${JSON.stringify(safetyAttributes, null, 2)}]`);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (prompt && prompt.debugInfo) {
|
|
228
|
-
prompt.debugInfo += `\n${JSON.stringify(data)}`;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export default PalmChatPlugin;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// palmCodeCompletionPlugin.js
|
|
2
|
-
|
|
3
|
-
import PalmCompletionPlugin from './palmCompletionPlugin.js';
|
|
4
|
-
|
|
5
|
-
// PalmCodeCompletionPlugin class for handling requests and responses to the PaLM API Code Completion API
|
|
6
|
-
class PalmCodeCompletionPlugin extends PalmCompletionPlugin {
|
|
7
|
-
constructor(pathway, model) {
|
|
8
|
-
super(pathway, model);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Set up parameters specific to the PaLM API Code Completion API
|
|
12
|
-
getRequestParameters(text, parameters, prompt, pathwayResolver) {
|
|
13
|
-
const { modelPromptText, tokenLength } = this.getCompiledPrompt(text, parameters, prompt);
|
|
14
|
-
// Define the model's max token length
|
|
15
|
-
const modelTargetTokenLength = this.getModelMaxPromptTokens();
|
|
16
|
-
|
|
17
|
-
const truncatedPrompt = this.truncatePromptIfNecessary(modelPromptText, tokenLength, this.getModelMaxTokenLength(), modelTargetTokenLength, pathwayResolver);
|
|
18
|
-
|
|
19
|
-
const max_tokens = this.getModelMaxReturnTokens();
|
|
20
|
-
|
|
21
|
-
if (max_tokens < 0) {
|
|
22
|
-
throw new Error(`Prompt is too long to successfully call the model at ${tokenLength} tokens. The model will not be called.`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!truncatedPrompt) {
|
|
26
|
-
throw new Error(`Prompt is empty. The model will not be called.`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const requestParameters = {
|
|
30
|
-
instances: [
|
|
31
|
-
{ prefix: truncatedPrompt }
|
|
32
|
-
],
|
|
33
|
-
parameters: {
|
|
34
|
-
temperature: this.temperature ?? 0.7,
|
|
35
|
-
maxOutputTokens: max_tokens,
|
|
36
|
-
topP: parameters.topP ?? 0.95,
|
|
37
|
-
topK: parameters.topK ?? 40,
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
return requestParameters;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export default PalmCodeCompletionPlugin;
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// palmCompletionPlugin.js
|
|
2
|
-
|
|
3
|
-
import ModelPlugin from './modelPlugin.js';
|
|
4
|
-
import logger from '../../lib/logger.js';
|
|
5
|
-
|
|
6
|
-
// PalmCompletionPlugin class for handling requests and responses to the PaLM API Text Completion API
|
|
7
|
-
class PalmCompletionPlugin extends ModelPlugin {
|
|
8
|
-
constructor(pathway, model) {
|
|
9
|
-
super(pathway, model);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
truncatePromptIfNecessary (text, textTokenCount, modelMaxTokenCount, targetTextTokenCount, pathwayResolver) {
|
|
13
|
-
const maxAllowedTokens = textTokenCount + ((modelMaxTokenCount - targetTextTokenCount) * 0.5);
|
|
14
|
-
|
|
15
|
-
if (textTokenCount > maxAllowedTokens) {
|
|
16
|
-
pathwayResolver.logWarning(`Prompt is too long at ${textTokenCount} tokens (this target token length for this pathway is ${targetTextTokenCount} tokens because the response is expected to take up the rest of the model's max tokens (${modelMaxTokenCount}). Prompt will be truncated.`);
|
|
17
|
-
return pathwayResolver.truncate(text, maxAllowedTokens);
|
|
18
|
-
}
|
|
19
|
-
return text;
|
|
20
|
-
}
|
|
21
|
-
// Set up parameters specific to the PaLM API Text Completion API
|
|
22
|
-
getRequestParameters(text, parameters, prompt, pathwayResolver) {
|
|
23
|
-
const { modelPromptText, tokenLength } = this.getCompiledPrompt(text, parameters, prompt);
|
|
24
|
-
|
|
25
|
-
// Define the model's max token length
|
|
26
|
-
const modelTargetTokenLength = this.getModelMaxPromptTokens();
|
|
27
|
-
|
|
28
|
-
const truncatedPrompt = this.truncatePromptIfNecessary(modelPromptText, tokenLength, this.getModelMaxTokenLength(), modelTargetTokenLength, pathwayResolver);
|
|
29
|
-
|
|
30
|
-
const max_tokens = this.getModelMaxReturnTokens();
|
|
31
|
-
|
|
32
|
-
if (max_tokens < 0) {
|
|
33
|
-
throw new Error(`Prompt is too long to successfully call the model at ${tokenLength} tokens. The model will not be called.`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!truncatedPrompt) {
|
|
37
|
-
throw new Error(`Prompt is empty. The model will not be called.`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const requestParameters = {
|
|
41
|
-
instances: [
|
|
42
|
-
{ prompt: truncatedPrompt }
|
|
43
|
-
],
|
|
44
|
-
parameters: {
|
|
45
|
-
temperature: this.temperature ?? 0.7,
|
|
46
|
-
maxOutputTokens: max_tokens,
|
|
47
|
-
topP: parameters.topP ?? 0.95,
|
|
48
|
-
topK: parameters.topK ?? 40,
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return requestParameters;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Execute the request to the PaLM API Text Completion API
|
|
56
|
-
async execute(text, parameters, prompt, cortexRequest) {
|
|
57
|
-
const requestParameters = this.getRequestParameters(text, parameters, prompt, cortexRequest.pathwayResolver);
|
|
58
|
-
|
|
59
|
-
cortexRequest.data = { ...(cortexRequest.data || {}), ...requestParameters };
|
|
60
|
-
cortexRequest.params = {}; // query params
|
|
61
|
-
|
|
62
|
-
const gcpAuthTokenHelper = this.config.get('gcpAuthTokenHelper');
|
|
63
|
-
const authToken = await gcpAuthTokenHelper.getAccessToken();
|
|
64
|
-
cortexRequest.auth.Authorization = `Bearer ${authToken}`;
|
|
65
|
-
|
|
66
|
-
return this.executeRequest(cortexRequest);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Parse the response from the PaLM API Text Completion API
|
|
70
|
-
parseResponse(data) {
|
|
71
|
-
const { predictions } = data;
|
|
72
|
-
if (!predictions || !predictions.length) {
|
|
73
|
-
return data;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// if we got a predictions array back with more than one prediction, return the whole array
|
|
77
|
-
if (predictions.length > 1) {
|
|
78
|
-
return predictions;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// otherwise, return the content of the first prediction
|
|
82
|
-
// if it was blocked, return the blocked message
|
|
83
|
-
if (predictions[0].safetyAttributes?.blocked) {
|
|
84
|
-
return 'The response is blocked because the input or response potentially violates Google policies. Try rephrasing the prompt or adjusting the parameter settings. Currently, only English is supported.';
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const contentResult = predictions[0].content && predictions[0].content.trim();
|
|
88
|
-
return contentResult ?? null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Get the safetyAttributes from the PaLM API Text Completion API response data
|
|
92
|
-
getSafetyAttributes(data) {
|
|
93
|
-
const { predictions } = data;
|
|
94
|
-
if (!predictions || !predictions.length) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// if we got a predictions array back with more than one prediction, return the safetyAttributes of the first prediction
|
|
99
|
-
if (predictions.length > 1) {
|
|
100
|
-
return predictions[0].safetyAttributes ?? null;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// otherwise, return the safetyAttributes of the content of the first prediction
|
|
104
|
-
return predictions[0].safetyAttributes ?? null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Override the logging function to log the prompt and response
|
|
108
|
-
logRequestData(data, responseData, prompt) {
|
|
109
|
-
const safetyAttributes = this.getSafetyAttributes(responseData);
|
|
110
|
-
|
|
111
|
-
const instances = data && data.instances;
|
|
112
|
-
const modelInput = instances && instances[0] && instances[0].prompt;
|
|
113
|
-
|
|
114
|
-
if (modelInput) {
|
|
115
|
-
const { length, units } = this.getLength(modelInput);
|
|
116
|
-
logger.info(`[request sent containing ${length} ${units}]`);
|
|
117
|
-
logger.verbose(`${modelInput}`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const responseText = this.parseResponse(responseData);
|
|
121
|
-
const { length, units } = this.getLength(responseText);
|
|
122
|
-
logger.info(`[response received containing ${length} ${units}]`);
|
|
123
|
-
logger.verbose(`${responseText}`);
|
|
124
|
-
|
|
125
|
-
if (safetyAttributes) {
|
|
126
|
-
logger.warn(`[response contains safety attributes: ${JSON.stringify(safetyAttributes, null, 2)}]`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (prompt && prompt.debugInfo) {
|
|
130
|
-
prompt.debugInfo += `\n${JSON.stringify(data)}`;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export default PalmCompletionPlugin;
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
// test_palmChatPlugin.js
|
|
2
|
-
import test from 'ava';
|
|
3
|
-
import PalmChatPlugin from '../server/plugins/palmChatPlugin.js';
|
|
4
|
-
import { mockPathwayResolverMessages } from './mocks.js';
|
|
5
|
-
|
|
6
|
-
const { config, pathway, modelName, model } = mockPathwayResolverMessages;
|
|
7
|
-
|
|
8
|
-
test.beforeEach((t) => {
|
|
9
|
-
const palmChatPlugin = new PalmChatPlugin(pathway, model);
|
|
10
|
-
t.context = { palmChatPlugin };
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('convertMessagesToPalm', (t) => {
|
|
14
|
-
const { palmChatPlugin } = t.context;
|
|
15
|
-
const messages = [
|
|
16
|
-
{ role: 'system', content: 'System Message' },
|
|
17
|
-
{ role: 'user', content: 'User Message' },
|
|
18
|
-
{ role: 'user', content: 'User Message 2'},
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
const expectedResult = {
|
|
22
|
-
modifiedMessages: [
|
|
23
|
-
{ author: 'user', content: 'User Message\nUser Message 2' },
|
|
24
|
-
],
|
|
25
|
-
context: 'System Message',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('convertMessagesToPalm - already PaLM format', (t) => {
|
|
32
|
-
const { palmChatPlugin } = t.context;
|
|
33
|
-
const messages = [
|
|
34
|
-
{ author: 'user', content: 'User Message' },
|
|
35
|
-
{ author: 'user', content: 'User Message 2'},
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
const expectedResult = {
|
|
39
|
-
modifiedMessages: [
|
|
40
|
-
{ author: 'user', content: 'User Message\nUser Message 2' },
|
|
41
|
-
],
|
|
42
|
-
context: '',
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('convertMessagesToPalm - empty string roles', (t) => {
|
|
49
|
-
const { palmChatPlugin } = t.context;
|
|
50
|
-
const messages = [
|
|
51
|
-
{ role: '', content: 'Empty role message' },
|
|
52
|
-
{ role: 'user', content: 'User Message' },
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
const expectedResult = {
|
|
56
|
-
modifiedMessages: [
|
|
57
|
-
{ author: 'user', content: 'User Message' },
|
|
58
|
-
],
|
|
59
|
-
context: '',
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('convertMessagesToPalm - consecutive system messages', (t) => {
|
|
66
|
-
const { palmChatPlugin } = t.context;
|
|
67
|
-
const messages = [
|
|
68
|
-
{ role: 'system', content: 'System Message 1' },
|
|
69
|
-
{ role: 'system', content: 'System Message 2' },
|
|
70
|
-
{ role: 'user', content: 'User Message' },
|
|
71
|
-
];
|
|
72
|
-
|
|
73
|
-
const expectedResult = {
|
|
74
|
-
modifiedMessages: [
|
|
75
|
-
{ author: 'user', content: 'User Message' },
|
|
76
|
-
],
|
|
77
|
-
context: 'System Message 1\nSystem Message 2',
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test('convertMessagesToPalm - multiple authors', (t) => {
|
|
84
|
-
const { palmChatPlugin } = t.context;
|
|
85
|
-
const messages = [
|
|
86
|
-
{ role: 'system', content: 'System Message' },
|
|
87
|
-
{ author: 'user1', content: 'User1 Message' },
|
|
88
|
-
{ author: 'user1', content: 'User1 Message 2' },
|
|
89
|
-
{ author: 'user2', content: 'User2 Message' },
|
|
90
|
-
{ author: 'assistant', content: 'Assistant Message' },
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
const expectedResult = {
|
|
94
|
-
modifiedMessages: [
|
|
95
|
-
{ author: 'user1', content: 'User1 Message\nUser1 Message 2' },
|
|
96
|
-
{ author: 'user2', content: 'User2 Message' },
|
|
97
|
-
{ author: 'assistant', content: 'Assistant Message' },
|
|
98
|
-
],
|
|
99
|
-
context: 'System Message',
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('convertMessagesToPalm - no messages', (t) => {
|
|
106
|
-
const { palmChatPlugin } = t.context;
|
|
107
|
-
const messages = [];
|
|
108
|
-
|
|
109
|
-
const expectedResult = {
|
|
110
|
-
modifiedMessages: [],
|
|
111
|
-
context: '',
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test('convertMessagesToPalm - only system messages', (t) => {
|
|
118
|
-
const { palmChatPlugin } = t.context;
|
|
119
|
-
const messages = [
|
|
120
|
-
{ role: 'system', content: 'System Message 1' },
|
|
121
|
-
{ role: 'system', content: 'System Message 2' },
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
const expectedResult = {
|
|
125
|
-
modifiedMessages: [],
|
|
126
|
-
context: 'System Message 1\nSystem Message 2',
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
t.deepEqual(palmChatPlugin.convertMessagesToPalm(messages), expectedResult);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('getCompiledContext', (t) => {
|
|
133
|
-
const { palmChatPlugin } = t.context;
|
|
134
|
-
const text = 'Hello';
|
|
135
|
-
const parameters = { name: 'John' };
|
|
136
|
-
const context = '{{text}} from {{name}}';
|
|
137
|
-
|
|
138
|
-
const expectedResult = 'Hello from John';
|
|
139
|
-
|
|
140
|
-
t.is(palmChatPlugin.getCompiledContext(text, parameters, context), expectedResult);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test('getCompiledExamples', (t) => {
|
|
144
|
-
const { palmChatPlugin } = t.context;
|
|
145
|
-
const text = 'Greetings';
|
|
146
|
-
const parameters = { name: 'Jane' };
|
|
147
|
-
const examples = [
|
|
148
|
-
{
|
|
149
|
-
input: { content: 'Input: {{text}} from {{name}}' },
|
|
150
|
-
output: { content: 'Output: {{text}} to {{name}}' },
|
|
151
|
-
},
|
|
152
|
-
];
|
|
153
|
-
|
|
154
|
-
const expectedResult = [
|
|
155
|
-
{
|
|
156
|
-
input: { content: 'Input: Greetings from Jane' },
|
|
157
|
-
output: { content: 'Output: Greetings to Jane' },
|
|
158
|
-
},
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
t.deepEqual(palmChatPlugin.getCompiledExamples(text, parameters, examples), expectedResult);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test('getRequestParameters', (t) => {
|
|
165
|
-
const { palmChatPlugin } = t.context;
|
|
166
|
-
const text = 'Hello';
|
|
167
|
-
const parameters = { stream: false, name: 'John'};
|
|
168
|
-
const messages = [
|
|
169
|
-
{ role: 'system', content: 'System Message' },
|
|
170
|
-
{ role: 'user', content: 'Hello' },
|
|
171
|
-
{ role: 'assistant', content: 'What can I do for you?' },
|
|
172
|
-
{ role: 'user', content: 'Be my assistant!' },
|
|
173
|
-
];
|
|
174
|
-
const prompt = { context: '{{text}} from {{name}}', examples: [], messages };
|
|
175
|
-
|
|
176
|
-
const requestParameters = palmChatPlugin.getRequestParameters(text, parameters, prompt);
|
|
177
|
-
const requestMessages = requestParameters.instances[0].messages;
|
|
178
|
-
|
|
179
|
-
t.is(requestMessages[0].author, 'user');
|
|
180
|
-
t.is(requestMessages[0].content, 'Hello');
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test('getSafetyAttributes', (t) => {
|
|
184
|
-
const { palmChatPlugin } = t.context;
|
|
185
|
-
const responseData = {
|
|
186
|
-
predictions: [
|
|
187
|
-
{
|
|
188
|
-
safetyAttributes: {
|
|
189
|
-
blocked: false,
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const expectedResult = {
|
|
196
|
-
blocked: false,
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
t.deepEqual(palmChatPlugin.getSafetyAttributes(responseData), expectedResult);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test('parseResponse', (t) => {
|
|
203
|
-
const { palmChatPlugin } = t.context;
|
|
204
|
-
const responseData = {
|
|
205
|
-
predictions: [
|
|
206
|
-
{
|
|
207
|
-
candidates: [
|
|
208
|
-
{
|
|
209
|
-
content: 'Hello, how can I help you today?',
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
},
|
|
213
|
-
],
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
const expectedResult = 'Hello, how can I help you today?';
|
|
217
|
-
|
|
218
|
-
t.is(palmChatPlugin.parseResponse(responseData), expectedResult);
|
|
219
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// palmCompletionPlugin.test.js
|
|
2
|
-
|
|
3
|
-
import test from 'ava';
|
|
4
|
-
import PalmCompletionPlugin from '../server/plugins/palmCompletionPlugin.js';
|
|
5
|
-
import { mockPathwayResolverString } from './mocks.js';
|
|
6
|
-
|
|
7
|
-
const { config, pathway, modelName, model } = mockPathwayResolverString;
|
|
8
|
-
|
|
9
|
-
test.beforeEach((t) => {
|
|
10
|
-
const palmCompletionPlugin = new PalmCompletionPlugin(pathway, model);
|
|
11
|
-
t.context = { palmCompletionPlugin };
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test('getRequestParameters', (t) => {
|
|
15
|
-
const { palmCompletionPlugin } = t.context;
|
|
16
|
-
const text = 'Hello';
|
|
17
|
-
const parameters = { stream: false, name: 'John' };
|
|
18
|
-
const prompt = {prompt:'{{text}} from {{name}}'};
|
|
19
|
-
|
|
20
|
-
const requestParameters = palmCompletionPlugin.getRequestParameters(text, parameters, prompt);
|
|
21
|
-
const requestPrompt = requestParameters.instances[0].prompt;
|
|
22
|
-
|
|
23
|
-
t.is(requestPrompt, 'Hello from John');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('parseResponse', (t) => {
|
|
27
|
-
const { palmCompletionPlugin } = t.context;
|
|
28
|
-
const responseData = {
|
|
29
|
-
predictions: [
|
|
30
|
-
{
|
|
31
|
-
content: 'Hello, how can I help you today?',
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const expectedResult = 'Hello, how can I help you today?';
|
|
37
|
-
|
|
38
|
-
t.is(palmCompletionPlugin.parseResponse(responseData), expectedResult);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('getSafetyAttributes', (t) => {
|
|
42
|
-
const { palmCompletionPlugin } = t.context;
|
|
43
|
-
const responseData = {
|
|
44
|
-
predictions: [
|
|
45
|
-
{
|
|
46
|
-
safetyAttributes: {
|
|
47
|
-
blocked: false,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const expectedResult = {
|
|
54
|
-
blocked: false,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
t.deepEqual(palmCompletionPlugin.getSafetyAttributes(responseData), expectedResult);
|
|
58
|
-
});
|