promptdesk
Version:
PromptDesk Javascript SDK
187 lines (186 loc) • 7.14 kB
JavaScript
import axios from 'axios';
import { memoize } from './utils';
export class PromptDesk {
apiKey;
serviceUrl;
cache = {};
constructor(obj) {
this.apiKey = obj.apiKey || process.env.PROMPTDESK_API_KEY || '';
this.serviceUrl = obj.serviceUrl || process.env.PROMPTDESK_SERVICE_URL || '';
//remove trailing slash
this.serviceUrl = this.serviceUrl.replace(/\/$/, '');
}
async ping() {
try {
const headers = {
'Authorization': `Bearer ${this.apiKey}`,
};
const response = await axios.get(`${this.serviceUrl}/api/ping`, { headers });
if (response.status === 200) {
return response.data;
}
else {
// Log and throw error for non-200 status codes that Axios doesn't automatically reject
throw new Error(`FAILED: ${response.status}, data: ${JSON.stringify(response.data)}`);
}
}
catch (error) {
if (error.response) {
// Here we handle errors that Axios caught, which includes a response (e.g., server errors like 500)
throw new Error(`${error.response.status}, data: ${error.response.data.message}`);
}
else if (error.request) {
// The request was made but no response was received
throw new Error(`PromptDesk service not found.`);
}
else {
// Something happened in setting up the request that triggered an Error
throw new Error(`Error setting up the request: ${error.response?.data?.error || error.message}`);
}
}
}
convertToObject(string) {
// Check if input is already an object or an array
if (typeof string === 'object') {
return string;
}
// Unescape HTML entities
string = this.unescapeHtml(string);
// Trim whitespace
string = string.trim();
const regex = /('(?=(,\s*')))|('(?=:))|((?<=([:,]\s*))')|((?<={)')|('(?=}))/g;
string = string.replace(regex, '"');
try {
// Try parsing as JSON
return JSON.parse(string);
}
catch (e) {
// If JSON parsing fails, return null
return null;
}
}
unescapeHtml(string) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
''': "'",
''': "'"
};
return string.replace(/&|<|>|"|'|'/g, function (m) { return map[m]; });
}
async list() {
try {
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
};
const response = await axios.get(`${this.serviceUrl}/api/prompts`, { headers });
if (response.status === 200) {
return response.data;
}
else {
throw new Error(`Failed: ${response.status} ${response.statusText}`);
}
}
catch (error) {
throw new Error(`Request failed: ${error}`);
}
}
cachedCall = memoize(async (payload, headers) => {
return await axios.post(`${this.serviceUrl}/api/generate`, payload, { headers });
});
async generate(promptName, variables = {}, options) {
if (!this.apiKey) {
throw new Error("API_KEY is not set");
}
const chain = options?.chain;
const object = options?.object;
const cache = options?.cache;
let classification = options?.classification;
const payload = {
prompt_name: promptName,
variables: variables,
};
if (chain) {
payload['chain'] = {
uuid: chain.uuid,
name: chain.name,
};
}
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
};
try {
let response;
if (cache) {
payload['cache'] = true;
response = await this.cachedCall(JSON.stringify(payload), headers);
}
else {
response = await axios.post(`${this.serviceUrl}/api/generate`, payload, { headers });
}
if (response.status !== 200) {
// Log and throw error for non-200 status codes that Axios doesn't automatically reject
throw new Error(`FAILED: ${response.status}, data: ${JSON.stringify(response.data)}`);
}
const message = response.data.message;
let generatedString;
if (typeof message === 'string') {
generatedString = message;
}
else if ('content' in message) {
generatedString = message.content;
}
else {
throw new Error("Failed to generate output - content or message not found in response.");
}
if (object) {
return this.convertToObject(generatedString);
}
const defaultClassification = {
true: ["yes", "true", "1"],
false: ["no", "false", "0"],
};
if (classification) {
if (classification === true) {
classification = defaultClassification;
}
for (const key in classification) {
for (const value of classification[key]) {
if (generatedString.trim().toLowerCase().includes(value)) {
//check if key is a boolean
if (key.toLocaleLowerCase() === "true") {
return true;
}
else if (key.toLocaleLowerCase() === "false") {
return false;
}
else {
return key;
}
}
}
}
return null;
}
return generatedString;
}
catch (error) {
if (error.response) {
// Here we handle errors that Axios caught, which includes a response (e.g., server errors like 500)
throw new Error(`${error.response.status}, data: ${error.response.data.message}`);
}
else if (error.request) {
// The request was made but no response was received
throw new Error(`PromptDesk service not found.`);
}
else {
// Something happened in setting up the request that triggered an Error
throw new Error(`Error setting up the request: ${error.response?.data?.error || error.message}`);
}
}
}
}