UNPKG

auto-gpt-ts

Version:

my take of Auto-GPT in typescript

217 lines (216 loc) 10.3 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createEmbedding = exports.getAdaEmbedding = exports.createChatCompletion = exports.callAiFunction = exports.RetryOpenaiApi = void 0; const logging_1 = require("../logging"); const openai_1 = require("openai"); const api_manages_1 = require("./api-manages"); const config_1 = require("../config/config"); const configuration = new openai_1.Configuration({ apiKey: new config_1.Config().openaiApiKey, }); const openai = new openai_1.OpenAIApi(configuration); const logger = (0, logging_1.getLogger)("llm-utils"); function RetryOpenaiApi(numRetries = 10, backoffBase = 2.0, warnUser = true) { const retryLimitMsg = `Error: Reached rate limit, passing...`; const apiKeyErrorMsg = `Please double check that you have setup a PAID OpenAI API Account. You can read more here: https://significant-gravitas.github.io/Auto-GPT/setup/#getting-an-api-key`; const backoffMsg = `Error: API Bad gateway. Waiting {backoff} seconds...`; return (target, propertyKey) => { const originalMethod = target[propertyKey].bind(target); const replacedFunction = function (...args) { return __awaiter(this, void 0, void 0, function* () { let userWarned = !warnUser; for (let attempt = 1; attempt <= numRetries + 1; attempt++) { try { return yield originalMethod.apply(target, args); } catch (error) { if (error.httpStatus) { if (attempt === numRetries + 1) { throw error; } logger.debug(retryLimitMsg); if (!userWarned) { logger.error(apiKeyErrorMsg); userWarned = true; } } else if (error.httpStatus === 502) { if (attempt === numRetries + 1) { throw error; } const backoff = Math.pow(backoffBase, (attempt + 2)); logger.debug(backoffMsg.replace("{backoff}", `${backoff}`)); yield new Promise((resolve) => setTimeout(resolve, backoff * 1000)); throw error; } else { throw error; } } } Object.defineProperty(target, propertyKey, { value: replacedFunction, }); }); }; }; } exports.RetryOpenaiApi = RetryOpenaiApi; function callAiFunction(fnName, args, description, model = "") { return __awaiter(this, void 0, void 0, function* () { const cfg = new config_1.Config(); if (!model) { model = cfg.smartLlmModel; } // For each arg, if any are null, convert to "null": const parsedArgs = args.map((arg) => (arg !== null ? String(arg) : "null")); // Parse args to comma-separated string const argsStr = parsedArgs.join(", "); const messages = [ { role: "system", content: `You are now the following Python function: \`\`\`# ${description}\n${fnName}\`\`\`\n\nOnly respond with your \`return\` value.`, }, { role: "user", content: argsStr, }, ]; return (yield openai.createChatCompletion({ model, messages, temperature: 0, })).data.choices[0].message.content; }); } exports.callAiFunction = callAiFunction; /** Create a chat completion using the OpenAI API @param {Message[]} messages - The messages to send to the chat completion. @param {string} [model] - The model to use. Defaults to null. @param {number} [temperature] - The temperature to use. Defaults to 0.9. @param {number} [maxTokens] - The max tokens to use. Defaults to null. @returns {string} - The response from the chat completion. */ function createChatCompletion(messages, model = "", temperature, maxTokens) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const cfg = new config_1.Config(); if (!temperature) { temperature = cfg.temperature; } const num_retries = 10; let warned_user = false; logger.debug(`Creating chat completion with model ${model}, temperature ${temperature}, max_tokens ${maxTokens}`); const api_manager = new api_manages_1.ApiManager(); let response = undefined; for (let attempt = 0; attempt < num_retries; attempt++) { const backoff = Math.pow(2, (attempt + 2)); try { response = yield api_manager.createChatCompletion({ model, messages, temperature, max_tokens: maxTokens, }); break; } catch (error) { logger.debug(`Error: createChatCompletion returned: `, { error, messages }); if (/400/.test(error.message)) { // TODO: find rate limit error status code if (!warned_user) { logger.warn(`Please double check that you have setup a PAID OpenAI API Account. You can read more here: https://significant-gravitas.github.io/Auto-GPT/setup/#getting-an-api-key`); warned_user = true; } } else { if (/429/.test(error.message) || /ENOTFOUND/.test(error.message)) { logger.debug(`Retrying after ${backoff} seconds...`); yield new Promise((res) => setTimeout(res, backoff)); } else if (attempt === num_retries - 1) { return `Error: couldn't not get response from API.`; } else { throw `Error: couldn't not get response from API.`; } } logger.debug(`Error: API Bad gateway. Waiting ${backoff} seconds...`); yield new Promise((res) => setTimeout(res, backoff)); } } if (!response) { logger.info("FAILED TO GET RESPONSE FROM OPENAI Auto-GPT has failed to get a response from OpenAI's services. Try running Auto-GPT again, and if the problem the persists try running it with --debug."); if (cfg.debugMode) { throw new Error(`Failed to get response after ${num_retries} retries`); } else { process.exit(1); } } let resp = (_b = (_a = response === null || response === void 0 ? void 0 : response.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b["content"]; return resp; }); } exports.createChatCompletion = createChatCompletion; /** * Get an embedding from the ada model. * * @param {string} text - The text to embed. * @returns {number[]} - The embedding. */ function getAdaEmbedding(text) { return __awaiter(this, void 0, void 0, function* () { const model = "text-embedding-ada-002"; const sanitizedText = text.replace("\n", " "); const kwargs = { model }; const embedding = yield LlmUtils.createEmbedding(sanitizedText, kwargs); const apiManager = new api_manages_1.ApiManager(); apiManager.updateCost(embedding.usage.prompt_tokens, 0, model); return embedding.data[0].embedding; }); } exports.getAdaEmbedding = getAdaEmbedding; class LlmUtils { /** warped in class for decorating */ static createEmbedding(text, ..._) { return __awaiter(this, void 0, void 0, function* () { const res = yield openai.createEmbedding(Object.assign({ input: [text], model: "text-embedding-ada-002" }, _)); return res.data; }); } } __decorate([ RetryOpenaiApi(), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object]), __metadata("design:returntype", Promise) ], LlmUtils, "createEmbedding", null); /** * Creates an embedding using the OpenAI API * @param {string} text - The text to embed. * @param {...any} _ - Additional arguments to pass to the OpenAI API embedding creation call. * @returns {openai.Embedding} - The embedding object. */ exports.createEmbedding = LlmUtils.createEmbedding; //# sourceMappingURL=llm-utils.js.map