UNPKG

@maximai/maxim-js

Version:

Maxim AI JS SDK. Visit https://getmaxim.ai for more info.

833 lines 36.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Maxim = void 0; const dataset_1 = require("./apis/dataset"); const folder_1 = require("./apis/folder"); const logs_1 = require("./apis/logs"); const prompt_1 = require("./apis/prompt"); const promptChain_1 = require("./apis/promptChain"); const inMemory_1 = require("./cache/inMemory"); const filterObjects_1 = require("./filterObjects"); const logger_1 = require("./logger/logger"); const testRun_1 = require("./testRun/testRun"); var EntityType; (function (EntityType) { EntityType[EntityType["PROMPT"] = 0] = "PROMPT"; EntityType[EntityType["PROMPT_CHAIN"] = 1] = "PROMPT_CHAIN"; EntityType[EntityType["FOLDER"] = 2] = "FOLDER"; })(EntityType || (EntityType = {})); class Maxim { constructor(config) { this.isPromptManagementEnabled = false; this.loggers = new Map(); if (!config.apiKey) { throw new Error("[Maxim-SDK] API key is required"); } if (globalThis.__maxim__sdk__instances__ && globalThis.__maxim__sdk__instances__.get(config.apiKey)) { console.warn("[Maxim-SDK] You have initialized multiple instances of Maxim with the same API key."); } this.baseUrl = config.baseUrl || "https://app.getmaxim.ai"; this.apiKey = config.apiKey; this._raiseExceptions = config.raiseExceptions || false; this.APIService = { prompt: new prompt_1.MaximPromptAPI(this.baseUrl, this.apiKey), promptChain: new promptChain_1.MaximPromptChainAPI(this.baseUrl, this.apiKey), folder: new folder_1.MaximFolderAPI(this.baseUrl, this.apiKey), dataset: new dataset_1.MaximDatasetAPI(this.baseUrl, this.apiKey), logs: new logs_1.MaximLogsAPI(this.baseUrl, this.apiKey), }; this.isDebug = config.debug || false; this.cache = config.cache || new inMemory_1.MaximInMemoryCache(); if (config.promptManagement) { this.isPromptManagementEnabled = true; this.sync = this.syncEntities(); this.intervalHandle = setInterval(() => { this.syncEntities(); }, 1000 * 60); this.intervalHandle.unref(); } if (!globalThis.__maxim__sdk__instances__) { globalThis.__maxim__sdk__instances__ = new Map(); } globalThis.__maxim__sdk__instances__.set(this.apiKey, this); } async syncEntities() { try { return new Promise((resolve, reject) => { Promise.all([this.syncPrompts(), this.syncFolders(), this.syncPromptChains()]) .then(() => { resolve(); }) .catch((err) => { console.error(`[Maxim-SDK] ${err}`); resolve(); }); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing entities: ${err instanceof Error ? err.message : err}`); } } } async syncPrompts() { try { await this.APIService.prompt.getPrompts().then(async (prompts) => { if (this.isDebug) { console.log(`[Maxim-SDK] Syncing ${prompts.length} prompts`); } await Promise.all(prompts.map(async (prompt) => { try { await this.cache.set(this.getCacheKey(EntityType.PROMPT, prompt.promptId), JSON.stringify(prompt)); } catch (err) { console.error(err); } })); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing prompts: ${err instanceof Error ? err.message : err}`); } } } async syncPromptChains() { try { await this.APIService.promptChain.getPromptChains().then(async (promptChains) => { if (this.isDebug) { console.log(`[Maxim-SDK] Syncing ${promptChains.length} prompt chains`); } await Promise.all(promptChains.map(async (promptChain) => { try { await this.cache.set(this.getCacheKey(EntityType.PROMPT_CHAIN, promptChain.promptChainId), JSON.stringify(promptChain)); } catch (err) { console.error(err); } })); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing prompt chains: ${err instanceof Error ? err.message : err}`); } } } async syncFolders() { try { await this.APIService.folder.getFolders().then(async (folders) => { if (this.isDebug) { console.log(`[Maxim-SDK] Syncing ${folders.length} folders`); } await Promise.all(folders.map(async (folder) => { try { await this.cache.set(this.getCacheKey(EntityType.FOLDER, folder.id), JSON.stringify(folder)); } catch (err) { console.error(err); } })); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing folders: ${err instanceof Error ? err.message : err}`); } } } async getPromptFromCache(key) { try { let data = await this.cache.get(key); if (!data) { return null; } return JSON.parse(data); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getAllPromptsFromCache() { try { let keys = await this.cache.getAllKeys(); if (!keys) { return null; } let data = await Promise.all(keys.filter((key) => key.startsWith("prompt:")).map((key) => this.cache.get(key))); return data.filter((d) => d !== null).map((d) => JSON.parse(d)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching all prompts from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getPromptChainFromCache(key) { try { let data = await this.cache.get(key); if (!data) { return null; } return JSON.parse(data); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chain from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getAllPromptChainsFromCache() { try { let keys = await this.cache.getAllKeys(); if (!keys) { return null; } let data = await Promise.all(keys.filter((key) => key.startsWith("promptChain:")).map((key) => this.cache.get(key))); return data.filter((d) => d !== null).map((d) => JSON.parse(d)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching all prompt chains from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getFolderFromCache(key) { try { let data = await this.cache.get(key); if (!data) { return null; } return JSON.parse(data); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folder from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getAllFoldersFromCache() { try { let keys = await this.cache.getAllKeys(); if (!keys) { return null; } let data = await Promise.all(keys.filter((key) => key.startsWith("folder:")).map((key) => this.cache.get(key))); return data.filter((d) => d !== null).map((d) => JSON.parse(d)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching all folders from cache: ${err instanceof Error ? err.message : err}`); return null; } } } getCacheKey(entity, id) { switch (entity) { case EntityType.PROMPT: return `prompt:${id}`; case EntityType.PROMPT_CHAIN: return `promptChain:${id}`; case EntityType.FOLDER: return `folder:${id}`; } } getPromptVersionForRule(promptVersionAndRules, rule) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; try { if (rule) { let incomingQuery = { query: rule.query, operator: rule.operator, exactMatch: rule.exactMatch, }; const objects = []; Object.keys(promptVersionAndRules.rules).forEach((versionId) => { const versionRules = promptVersionAndRules.rules[versionId]; versionRules.forEach((versionRule) => { var _a; if (!versionRule.rules.query) { return; } if (rule.scopes) { Object.keys(rule.scopes).forEach((key) => { switch (key) { case "folder": break; default: throw new Error("Invalid scope added"); } }); } const version = promptVersionAndRules === null || promptVersionAndRules === void 0 ? void 0 : promptVersionAndRules.versions.find((v) => v.id === versionId); const query = versionRule.rules.query; if (!version) return; if ((_a = version.config) === null || _a === void 0 ? void 0 : _a.tags) { const parsedIncomingQuery = (0, filterObjects_1.parseIncomingQuery)(incomingQuery.query); const tags = version.config.tags; Object.keys(tags) .filter((key) => tags[key] !== undefined) .filter((key) => parsedIncomingQuery.map((incomingQueryRule) => incomingQueryRule.field).includes(key)) .forEach((key) => { query.rules.push({ field: key, operator: "=", value: tags[key] }); }); } objects.push({ query, id: versionId, }); }); }); const deployedVersionObject = (0, filterObjects_1.findBestMatch)(objects, incomingQuery); if (deployedVersionObject) { const deployedVersion = promptVersionAndRules === null || promptVersionAndRules === void 0 ? void 0 : promptVersionAndRules.versions.find((v) => v.id === deployedVersionObject.id); return { promptId: deployedVersion.promptId, versionId: deployedVersion.id, version: deployedVersion.version, messages: (_a = deployedVersion.config) === null || _a === void 0 ? void 0 : _a.messages, modelParameters: (_b = deployedVersion.config) === null || _b === void 0 ? void 0 : _b.modelParameters, model: (_c = deployedVersion.config) === null || _c === void 0 ? void 0 : _c.model, provider: (_d = deployedVersion.config) === null || _d === void 0 ? void 0 : _d.provider, tags: (_e = deployedVersion.config) === null || _e === void 0 ? void 0 : _e.tags, run: (input, options) => { if (!deployedVersion) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt"); } return this.APIService.prompt.runPromptVersion(deployedVersion.id, input, options); }, }; } } else { for (const versionId in promptVersionAndRules.rules) { const versionRules = promptVersionAndRules.rules[versionId]; let isMatch = false; for (const rule of versionRules) { if (rule.rules.query === undefined || ((_f = rule.rules.query) === null || _f === void 0 ? void 0 : _f.rules.length) === 0) { isMatch = true; break; } } if (isMatch) { const deployedVersion = promptVersionAndRules.versions.find((v) => v.id === versionId); return { promptId: deployedVersion.promptId, versionId: deployedVersion.id, version: deployedVersion.version, messages: (_g = deployedVersion.config) === null || _g === void 0 ? void 0 : _g.messages, modelParameters: (_h = deployedVersion.config) === null || _h === void 0 ? void 0 : _h.modelParameters, model: (_j = deployedVersion.config) === null || _j === void 0 ? void 0 : _j.model, provider: (_k = deployedVersion.config) === null || _k === void 0 ? void 0 : _k.provider, tags: (_l = deployedVersion.config) === null || _l === void 0 ? void 0 : _l.tags, run: (input, options) => { if (!deployedVersion) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt"); } return this.APIService.prompt.runPromptVersion(deployedVersion.id, input, options); }, }; } } } if (promptVersionAndRules.fallbackVersion) { return { promptId: promptVersionAndRules.fallbackVersion.promptId, versionId: promptVersionAndRules.fallbackVersion.id, version: promptVersionAndRules.fallbackVersion.version, ...promptVersionAndRules.fallbackVersion.config, run: (input, options) => { var _a; if (!((_a = promptVersionAndRules.fallbackVersion) === null || _a === void 0 ? void 0 : _a.id)) { throw new Error("[Maxim-SDK] Deployed fallback version missing while attempting to run prompt"); } return this.APIService.prompt.runPromptVersion(promptVersionAndRules.fallbackVersion.id, input, options); }, }; } return undefined; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt version for rule: ${err instanceof Error ? err.message : err}`); return undefined; } } } getPromptChainVersionForRule(promptChainVersionAndRules, rule) { var _a, _b, _c; try { if (rule) { let incomingQuery = { query: rule.query, operator: rule.operator, exactMatch: rule.exactMatch, }; const objects = []; Object.keys(promptChainVersionAndRules.rules).forEach((versionId) => { const versionRules = promptChainVersionAndRules.rules[versionId]; versionRules.forEach((versionRule) => { if (!versionRule.rules.query) { return; } if (rule.scopes) { Object.keys(rule.scopes).forEach((key) => { switch (key) { case "folder": break; default: throw new Error("Invalid scope added"); } }); } const version = promptChainVersionAndRules === null || promptChainVersionAndRules === void 0 ? void 0 : promptChainVersionAndRules.versions.find((v) => v.id === versionId); const query = versionRule.rules.query; if (!version) return; objects.push({ query, id: versionId, }); }); }); const deployedVersionObject = (0, filterObjects_1.findBestMatch)(objects, incomingQuery); if (deployedVersionObject) { const deployedVersion = promptChainVersionAndRules === null || promptChainVersionAndRules === void 0 ? void 0 : promptChainVersionAndRules.versions.find((v) => v.id === deployedVersionObject.id); return { promptChainId: deployedVersion.promptChainId, versionId: deployedVersion.id, version: deployedVersion.version, nodes: (_a = deployedVersion.config) === null || _a === void 0 ? void 0 : _a.nodes.filter((n) => "prompt" in n), run: (input, options) => { if (!(deployedVersion === null || deployedVersion === void 0 ? void 0 : deployedVersion.id)) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt chain"); } return this.APIService.promptChain.runPromptChainVersion(deployedVersion.id, input, options); }, }; } } else { for (const versionId in promptChainVersionAndRules.rules) { const versionRules = promptChainVersionAndRules.rules[versionId]; let isMatch = false; for (const rule of versionRules) { if (rule.rules.query === undefined || ((_b = rule.rules.query) === null || _b === void 0 ? void 0 : _b.rules.length) === 0) { isMatch = true; break; } } if (isMatch) { const deployedVersion = promptChainVersionAndRules.versions.find((v) => v.id === versionId); return { promptChainId: deployedVersion.promptChainId, versionId: deployedVersion.id, version: deployedVersion.version, nodes: (_c = deployedVersion.config) === null || _c === void 0 ? void 0 : _c.nodes.filter((n) => "prompt" in n), run: (input, options) => { if (!(deployedVersion === null || deployedVersion === void 0 ? void 0 : deployedVersion.id)) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt chain"); } return this.APIService.promptChain.runPromptChainVersion(deployedVersion.id, input, options); }, }; } } } if (promptChainVersionAndRules.fallbackVersion) { return { promptChainId: promptChainVersionAndRules.fallbackVersion.promptChainId, versionId: promptChainVersionAndRules.fallbackVersion.id, version: promptChainVersionAndRules.fallbackVersion.version, nodes: promptChainVersionAndRules.fallbackVersion.config ? promptChainVersionAndRules.fallbackVersion.config.nodes.filter((n) => "prompt" in n) : [], run: (input, options) => { var _a; if (!((_a = promptChainVersionAndRules.fallbackVersion) === null || _a === void 0 ? void 0 : _a.id)) { throw new Error("[Maxim-SDK] Deployed fallback version missing while attempting to run prompt chain"); } return this.APIService.promptChain.runPromptChainVersion(promptChainVersionAndRules.fallbackVersion.id, input, options); }, }; } return undefined; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chain version for rule: ${err instanceof Error ? err.message : err}`); return undefined; } } } getFoldersForRule(folders, rule) { try { let incomingQuery = { query: rule.query, operator: rule.operator, exactMatch: rule.exactMatch, }; const objects = []; folders.forEach((folder) => { const query = { combinator: "AND", not: false, rules: [], }; if (!folder.tags) { return; } const parsedIncomingQuery = (0, filterObjects_1.parseIncomingQuery)(incomingQuery.query); const tags = folder.tags; Object.keys(tags) .filter((key) => tags[key] !== undefined) .filter((key) => parsedIncomingQuery.map((rule) => rule.field).includes(key)) .forEach((key) => { query.rules.push({ field: key, operator: "=", value: tags[key] }); }); if (query.rules.length === 0) { return; } objects.push({ query, id: folder.id, }); }); const folderObjects = (0, filterObjects_1.findAllMatches)(objects, incomingQuery); const ids = folderObjects.map((fo) => fo.id); return folders.filter((f) => ids.includes(f.id)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folders for rule: ${err instanceof Error ? err.message : err}`); return undefined; } } } async getPrompt(promptId, rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; const key = this.getCacheKey(EntityType.PROMPT, promptId); let versionAndRules = await this.getPromptFromCache(key); if (versionAndRules === null) { versionAndRules = await this.APIService.prompt.getPrompt(promptId); if (versionAndRules.versions.length === 0) { throw new Error(`No active deployments found for Prompt ${promptId}`); } await this.cache.set(promptId, JSON.stringify(versionAndRules)); } if (!versionAndRules) { throw new Error(`No active deployments found for Prompt ${promptId}`); } const prompt = this.getPromptVersionForRule(versionAndRules, rule); if (!prompt) { throw new Error(`No active deployments found for Prompt ${promptId}`); } return prompt; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt: ${err instanceof Error ? err.message : err}`); return undefined; } } } async getPrompts(rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; let versionAndRules = await this.getAllPromptsFromCache(); if (versionAndRules === null || versionAndRules.length === 0) { await this.syncEntities(); versionAndRules = await this.getAllPromptsFromCache(); } if (!versionAndRules) { throw new Error(`No active deployments found for any prompt`); } let prompts = versionAndRules .filter((v) => { if (Object.keys(rule.scopes).length === 0) { return true; } if (rule.scopes["folder"]) { return v.folderId === rule.scopes["folder"]; } return true; }) .map((v) => this.getPromptVersionForRule(v, rule)) .filter((p) => p !== undefined); if (prompts.length === 0) { throw new Error(`No active deployments found for any prompt`); } return prompts; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompts: ${err instanceof Error ? err.message : err}`); return undefined; } } } async getPromptChain(promptChainId, rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; const key = this.getCacheKey(EntityType.PROMPT_CHAIN, promptChainId); let versionAndRules = await this.getPromptChainFromCache(key); if (versionAndRules === null) { versionAndRules = await this.APIService.promptChain.getPromptChain(promptChainId); if (versionAndRules.versions.length === 0) { throw new Error(`No active deployments found for Prompt Chain ${promptChainId}`); } await this.cache.set(promptChainId, JSON.stringify(versionAndRules)); } if (!versionAndRules) { throw new Error(`No active deployments found for Prompt Chain ${promptChainId}`); } const promptChain = this.getPromptChainVersionForRule(versionAndRules, rule); if (!promptChain) { throw new Error(`No active deployments found for Prompt Chain ${promptChainId}`); } return promptChain; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chain: ${err instanceof Error ? err.message : err}`); return undefined; } } } async getPromptChains(rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; let versionAndRules = await this.getAllPromptChainsFromCache(); if (versionAndRules === null || versionAndRules.length === 0) { await this.syncEntities(); versionAndRules = await this.getAllPromptChainsFromCache(); } if (!versionAndRules) { throw new Error(`No active deployments found for any prompt chain`); } let promptChains = versionAndRules .filter((v) => { if (Object.keys(rule.scopes).length === 0) { return true; } if (rule.scopes["folder"]) { return v.folderId === rule.scopes["folder"]; } return true; }) .map((v) => this.getPromptChainVersionForRule(v, rule)) .filter((p) => p !== undefined); if (promptChains.length === 0) { throw new Error(`No active deployments found for any prompt chain`); } return promptChains; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chains: ${err instanceof Error ? err.message : err}`); return undefined; } } } async getFolderById(folderId) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; const key = this.getCacheKey(EntityType.FOLDER, folderId); let folder = await this.getFolderFromCache(key); if (folder === null) { folder = await this.APIService.folder.getFolder(folderId); if (!folder) { throw new Error(`No folder found with id ${folderId}`); } await this.cache.set(key, JSON.stringify(folder)); } return folder; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folder by id: ${err instanceof Error ? err.message : err}`); return undefined; } } } async getFolders(rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; let folders = await this.getAllFoldersFromCache(); if (folders === null || folders.length === 0) { await this.syncEntities(); folders = await this.getAllFoldersFromCache(); } if (!folders) { throw new Error(`No folders found`); } return this.getFoldersForRule(folders, rule); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folders: ${err instanceof Error ? err.message : err}`); return undefined; } } } async addDatasetEntries(datasetId, entries) { try { return this.APIService.dataset.addDatasetEntries(datasetId, entries); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while adding dataset entries: ${err instanceof Error ? err.message : err}`); } } } async logger(config) { try { if (this.isPromptManagementEnabled) await this.sync; const exists = await this.APIService.logs.doesLogRepositoryExist(config.id); if (!exists) { if (config.id) { throw new Error(`Log repository not found.`); } } if (this.loggers.has(config.id)) { return this.loggers.get(config.id); } const logger = new logger_1.MaximLogger({ config: config, apiKey: this.apiKey, baseUrl: this.baseUrl, isDebug: this.isDebug, cache: this.cache, raiseExceptions: this._raiseExceptions, }); this.loggers.set(config.id, logger); return logger; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while creating logger: ${err instanceof Error ? err.message : err}`); return undefined; } } } createTestRun(name, inWorkspaceId) { return (0, testRun_1.createTestRunBuilder)({ baseUrl: this.baseUrl, apiKey: this.apiKey, name, workspaceId: inWorkspaceId, evaluators: [] }); } async cleanup() { try { if (this.intervalHandle) { clearInterval(this.intervalHandle); } await Promise.all(Array.from(this.loggers.values()).map((logger) => logger.cleanup())); if (globalThis.__maxim__sdk__instances__.get(this.apiKey)) { globalThis.__maxim__sdk__instances__.delete(this.apiKey); } this.APIService.prompt.destroyAgents(); this.APIService.promptChain.destroyAgents(); this.APIService.folder.destroyAgents(); this.APIService.dataset.destroyAgents(); this.APIService.logs.destroyAgents(); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while cleaning up: ${err instanceof Error ? err.message : err}`); } } } } exports.Maxim = Maxim; //# sourceMappingURL=maxim.js.map