@aj-archipelago/cortex 1.1.35 → 1.1.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
CHANGED
|
@@ -503,7 +503,8 @@ The configuration should include the following properties:
|
|
|
503
503
|
"awsAccessKeyId": "your_access_key_id", // Only for AWS S3
|
|
504
504
|
"awsSecretAccessKey": "your_secret_access_key", // Only for AWS S3
|
|
505
505
|
"awsRegion": "your_aws_region", // Only for AWS S3
|
|
506
|
-
"awsBucketName": "cortexdynamicpathways" // Optional, default is "cortexdynamicpathways"
|
|
506
|
+
"awsBucketName": "cortexdynamicpathways", // Optional, default is "cortexdynamicpathways"
|
|
507
|
+
"publishKey": "your_publish_key"
|
|
507
508
|
}
|
|
508
509
|
```
|
|
509
510
|
|
|
@@ -559,7 +560,7 @@ query ExecuteWorkspace($userId: String!, $pathwayName: String!, $text: String!)
|
|
|
559
560
|
|
|
560
561
|
To ensure the security of dynamic pathways:
|
|
561
562
|
|
|
562
|
-
1. A `
|
|
563
|
+
1. A `publishKey` must be set in the dynamic pathways configuration to enable pathway publishing.
|
|
563
564
|
2. This key must be provided in the `key` parameter when adding, updating, or deleting pathways.
|
|
564
565
|
3. Each pathway is associated with a `userId` and `secret`. The secret must be provided to modify or delete an existing pathway.
|
|
565
566
|
|
|
@@ -567,4 +568,4 @@ To ensure the security of dynamic pathways:
|
|
|
567
568
|
|
|
568
569
|
Each instance of Cortex maintains its own local cache of pathways. On every dynamic pathway request, it checks if the local cache is up to date by comparing the last modified timestamp of the storage with the last update time of the local cache. If the local cache is out of date, it reloads the pathways from storage.
|
|
569
570
|
|
|
570
|
-
This approach ensures that all instances of Cortex will eventually have access to the most up-to-date dynamic pathways without requiring immediate synchronization.
|
|
571
|
+
This approach ensures that all instances of Cortex will eventually have access to the most up-to-date dynamic pathways without requiring immediate synchronization.
|
package/config.js
CHANGED
|
@@ -321,6 +321,7 @@ const createDynamicPathwayManager = async (config, basePathway) => {
|
|
|
321
321
|
awsSecretAccessKey: dynamicPathwayConfig.awsSecretAccessKey,
|
|
322
322
|
awsRegion: dynamicPathwayConfig.awsRegion,
|
|
323
323
|
awsBucketName: dynamicPathwayConfig.awsBucketName || 'cortexdynamicpathways',
|
|
324
|
+
publishKey: dynamicPathwayConfig.publishKey,
|
|
324
325
|
};
|
|
325
326
|
|
|
326
327
|
const pathwayManager = new PathwayManager(storageConfig, basePathway);
|
package/lib/pathwayManager.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BlobServiceClient } from '@azure/storage-blob';
|
|
2
2
|
import { S3 } from '@aws-sdk/client-s3';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
4
5
|
import logger from './logger.js';
|
|
5
|
-
const { PATHWAY_PUBLISH_KEY } = process.env;
|
|
6
6
|
|
|
7
7
|
class StorageStrategy {
|
|
8
8
|
async load() { throw new Error('Not implemented'); }
|
|
@@ -20,6 +20,8 @@ class LocalStorage extends StorageStrategy {
|
|
|
20
20
|
if (!fs.existsSync(this.filePath)) {
|
|
21
21
|
// create it. log
|
|
22
22
|
logger.info(`Creating dynamic pathways local file: ${this.filePath}`);
|
|
23
|
+
// create directory if it doesn't exist
|
|
24
|
+
await fs.promises.mkdir(path.dirname(this.filePath), { recursive: true });
|
|
23
25
|
await fs.promises.writeFile(this.filePath, JSON.stringify({}));
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -219,6 +221,7 @@ class S3Storage extends StorageStrategy {
|
|
|
219
221
|
class PathwayManager {
|
|
220
222
|
constructor(config, basePathway) {
|
|
221
223
|
this.storage = this.getStorageStrategy(config);
|
|
224
|
+
this.publishKey = config.publishKey;
|
|
222
225
|
this.pathways = {};
|
|
223
226
|
this.lastUpdated = 0;
|
|
224
227
|
this.basePathway = basePathway;
|
|
@@ -226,6 +229,10 @@ class PathwayManager {
|
|
|
226
229
|
if (config.storageType === 'local') {
|
|
227
230
|
logger.warn('WARNING: Local file storage is being used for dynamic pathways. If there are multiple instances of Cortex, they will not be synced. Consider using cloud storage such as S3 or Azure for production environments.');
|
|
228
231
|
}
|
|
232
|
+
|
|
233
|
+
if (!this.publishKey) {
|
|
234
|
+
logger.warn('WARNING: dynamicPathwaysConfig.publishKey is not set. Dynamic pathways will not be editable in this instance of Cortex.');
|
|
235
|
+
}
|
|
229
236
|
}
|
|
230
237
|
|
|
231
238
|
getStorageStrategy(config) {
|
|
@@ -283,6 +290,7 @@ class PathwayManager {
|
|
|
283
290
|
throw new Error('Both userId and secret are mandatory for adding or updating a pathway');
|
|
284
291
|
}
|
|
285
292
|
|
|
293
|
+
await this.getLatestPathways();
|
|
286
294
|
this.pathways[userId] = this.pathways[userId] || {};
|
|
287
295
|
|
|
288
296
|
if (this.pathways[userId][name] && this.pathways[userId][name].secret !== secret) {
|
|
@@ -296,9 +304,12 @@ class PathwayManager {
|
|
|
296
304
|
}
|
|
297
305
|
|
|
298
306
|
async removePathway(name, userId, secret) {
|
|
307
|
+
await this.getLatestPathways();
|
|
308
|
+
|
|
299
309
|
if (!this.pathways[userId] || !this.pathways[userId][name]) {
|
|
300
310
|
return;
|
|
301
311
|
}
|
|
312
|
+
|
|
302
313
|
if (this.pathways[userId][name].secret !== secret) {
|
|
303
314
|
throw new Error('Invalid secret');
|
|
304
315
|
}
|
|
@@ -344,11 +355,11 @@ class PathwayManager {
|
|
|
344
355
|
return {
|
|
345
356
|
Mutation: {
|
|
346
357
|
putPathway: async (_, { name, pathway, userId, secret, displayName, key }) => {
|
|
347
|
-
if (!
|
|
358
|
+
if (!this.publishKey) {
|
|
348
359
|
throw new Error("Invalid configuration. Pathway publishing key is not configured in Cortex.")
|
|
349
360
|
}
|
|
350
361
|
|
|
351
|
-
if (key !==
|
|
362
|
+
if (key !== this.publishKey) {
|
|
352
363
|
throw new Error('Invalid pathway publishing key. The key provided did not match the key configured in Cortex.');
|
|
353
364
|
}
|
|
354
365
|
|
|
@@ -360,10 +371,10 @@ class PathwayManager {
|
|
|
360
371
|
}
|
|
361
372
|
},
|
|
362
373
|
deletePathway: async (_, { name, userId, secret, key }) => {
|
|
363
|
-
if (!
|
|
374
|
+
if (!this.publishKey) {
|
|
364
375
|
throw new Error("Invalid configuration. Pathway publishing key is not configured in Cortex.")
|
|
365
376
|
}
|
|
366
|
-
if (key !==
|
|
377
|
+
if (key !== this.publishKey) {
|
|
367
378
|
throw new Error('Invalid pathway publishing key. The key provided did not match the key configured in Cortex.');
|
|
368
379
|
}
|
|
369
380
|
|
|
@@ -378,7 +389,7 @@ class PathwayManager {
|
|
|
378
389
|
};
|
|
379
390
|
}
|
|
380
391
|
|
|
381
|
-
async
|
|
392
|
+
async getLatestPathways() {
|
|
382
393
|
try {
|
|
383
394
|
const currentTimestamp = await this.storage.getLastModified();
|
|
384
395
|
|
|
@@ -390,13 +401,13 @@ class PathwayManager {
|
|
|
390
401
|
|
|
391
402
|
return this.pathways;
|
|
392
403
|
} catch (error) {
|
|
393
|
-
logger.error('Error in
|
|
404
|
+
logger.error('Error in getLatestPathways:', error);
|
|
394
405
|
throw error;
|
|
395
406
|
}
|
|
396
407
|
}
|
|
397
408
|
|
|
398
409
|
async getPathway(userId, pathwayName) {
|
|
399
|
-
const pathways = await this.
|
|
410
|
+
const pathways = await this.getLatestPathways();
|
|
400
411
|
|
|
401
412
|
if (!pathways[userId] || !pathways[userId][pathwayName]) {
|
|
402
413
|
throw new Error(`Pathway '${pathwayName}' not found for user '${userId}'`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aj-archipelago/cortex",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.36",
|
|
4
4
|
"description": "Cortex is a GraphQL API for AI. It provides a simple, extensible interface for using AI services from OpenAI, Azure and others.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// replicateApiPlugin.js
|
|
2
|
+
import ModelPlugin from "./modelPlugin.js";
|
|
3
|
+
import logger from "../../lib/logger.js";
|
|
4
|
+
|
|
5
|
+
class ReplicateApiPlugin extends ModelPlugin {
|
|
6
|
+
constructor(pathway, model) {
|
|
7
|
+
super(pathway, model);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Set up parameters specific to the Replicate API
|
|
11
|
+
getRequestParameters(text, parameters, prompt) {
|
|
12
|
+
const combinedParameters = { ...this.promptParameters, ...parameters };
|
|
13
|
+
const { modelPromptText } = this.getCompiledPrompt(
|
|
14
|
+
text,
|
|
15
|
+
parameters,
|
|
16
|
+
prompt,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const requestParameters = {
|
|
20
|
+
input: {
|
|
21
|
+
aspect_ratio: "1:1",
|
|
22
|
+
output_format: "webp",
|
|
23
|
+
output_quality: 80,
|
|
24
|
+
prompt: modelPromptText,
|
|
25
|
+
//prompt_upsampling: false,
|
|
26
|
+
//safety_tolerance: 5,
|
|
27
|
+
go_fast: true,
|
|
28
|
+
megapixels: "1",
|
|
29
|
+
num_outputs: combinedParameters.numberResults,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return requestParameters;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Execute the request to the Replicate API
|
|
37
|
+
async execute(text, parameters, prompt, cortexRequest) {
|
|
38
|
+
const requestParameters = this.getRequestParameters(
|
|
39
|
+
text,
|
|
40
|
+
parameters,
|
|
41
|
+
prompt,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
cortexRequest.data = requestParameters;
|
|
45
|
+
cortexRequest.params = requestParameters.params;
|
|
46
|
+
|
|
47
|
+
return this.executeRequest(cortexRequest);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Parse the response from the Replicate API
|
|
51
|
+
parseResponse(data) {
|
|
52
|
+
if (data.data) {
|
|
53
|
+
return JSON.stringify(data.data);
|
|
54
|
+
}
|
|
55
|
+
return JSON.stringify(data);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Override the logging function to display the request and response
|
|
59
|
+
logRequestData(data, responseData, prompt) {
|
|
60
|
+
const modelInput = data?.input?.prompt;
|
|
61
|
+
|
|
62
|
+
logger.verbose(`${modelInput}`);
|
|
63
|
+
logger.verbose(`${this.parseResponse(responseData)}`);
|
|
64
|
+
|
|
65
|
+
prompt &&
|
|
66
|
+
prompt.debugInfo &&
|
|
67
|
+
(prompt.debugInfo += `\n${JSON.stringify(data)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default ReplicateApiPlugin;
|