UNPKG

openai-nodejs

Version:

A non-official OpenAI API wrapper for node.

678 lines (591 loc) 28.8 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>OpenAI NodeJS: index.js</title> <link type="text/css" rel="stylesheet" href="styles/vendor/prism-tomorrow-night.css"> <link type="text/css" rel="stylesheet" href="styles/styles.css"> </head> <body> <header class="layout-header"> <h1> <a href="./index.html"> OpenAI NodeJS </a> </h1> <nav class="layout-nav"> <ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="OpenAI.html">OpenAI</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#answer">answer</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#classificate">classificate</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#complete">complete</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#decode">decode</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#deleteFile">deleteFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#encode">encode</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#getEngine">getEngine</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#getEngines">getEngines</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#getFile">getFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#getFiles">getFiles</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#search">search</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#tokens">tokens</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="OpenAI.html#uploadFile">uploadFile</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#Answer">Answer</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#AnswerBody">AnswerBody</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#AnswerDocument">AnswerDocument</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#Classification">Classification</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#ClassificationBody">ClassificationBody</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#ClassificationExample">ClassificationExample</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#Completion">Completion</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#CompletionBody">CompletionBody</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#CompletionChoice">CompletionChoice</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#DeletedFile">DeletedFile</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#Engine">Engine</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#File">File</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#Search">Search</a></span></li><li class="nav-item"><span class="nav-item-type type-typedef" title="typedef">T</span><span class="nav-item-name is-typedef"><a href="global.html#SearchBody">SearchBody</a></span></li> </nav> </header> <main class="layout-main layout-content--source"> <div class="container"> <p class="page-kind">source</p> <h1 class="page-title">index.js</h1> <section> <article> <pre id="source" class="source-page line-numbers"><code class="language-js">const gpt3encoder = require('gpt-3-encoder'); const { typeCheck } = require('type-check'); const FormData = require('form-data'); const axios = require('axios').create({ baseURL: 'https://api.openai.com/v1' }); const stream = require('stream'); const assert = require('assert'); const parameters = require('./utils/parameters.json'); const RequestError = require('./utils/RequestError'); const { ReadStream } = require('fs'); /** * OpenAI client library. */ class OpenAI { #api_key; #organization_id; /** * @param {String} key API key * @param {String} [organization=null] Organization ID * @param {String} [engine=davinci] The engine you will use in your requests * @see https://beta.openai.com/docs/api-reference/authentication */ constructor(key, organization = null, engine = 'davinci') { assert.strictEqual(typeof key, 'string', 'key must be a string'); assert.ok(organization ? typeof organization === 'string' : true, 'organization must be a string'); assert.ok(engine ? typeof engine === 'string' : true, 'engine must be a string'); this.#api_key = key; this.#organization_id = organization; this.engine = engine; } _request(endpoint = '', request_content = {}, request_type = 'POST', custom_header = {}) { assert.strictEqual(typeof endpoint, 'string', 'endpoint must be a string'); assert.strictEqual(typeof request_content, 'object', 'request_content must be an object'); assert.strictEqual(typeof request_type, 'string', 'request_type must be a string'); assert.strictEqual(typeof custom_header, 'object', 'custom_header must be a string'); request_type = request_type.toUpperCase(); assert.ok(request_type === 'GET' || request_type === 'POST' || request_type === 'DELETE', 'invalid request_type'); let headers = { 'Authorization': 'Bearer ' + this.#api_key, } if (this.#organization_id) headers['OpenAI-Organization'] = this.#organization_id; if (request_type === 'POST') headers['content-type'] = 'application/json'; headers = {...headers, ...custom_header}; if (request_type === 'POST') return axios.post(endpoint, request_content, {headers}); else if (request_type === 'GET') return axios.get(endpoint, {headers, params: request_content}); else if (request_type === 'DELETE') return axios.delete(endpoint, {headers, request_content}); } /** * @typedef {Object} Engine * * @property {String} id * @property {String} object * @property {Number|null} created * @property {Number|null} max_replicas * @property {String} owner * @property {any} permissions * @property {boolean} ready * @property {boolean|null} ready_replicas * @property {any} ready_replicas * @see https://beta.openai.com/docs/api-reference/engines */ /** * Lists the currently available engines, and provides basic information about each one such as the owner and availability. * @returns {Promise&lt;Array&lt;Engine>>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * client.getEngines() * .then(engines => { * console.log(`Engines: ${engines.map(engine => engine.id).join(', ')}`); * }) * .catch(console.error); * * @see https://beta.openai.com/docs/api-reference/engines/list */ async getEngines() { return this._request('/engines', {}, 'GET') .then(res => res.data.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * Retrieves an engine instance, providing basic information about the engine such as the owner and availability. * @param {String} engine The ID of the engine to use for this request * @returns {Promise&lt;Engine>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * client.getEngine('davinci') * .then(engine => { * console.log(`Engine owner: ${engine.owner}`); * }) * .catch(console.error); * * @see https://beta.openai.com/docs/api-reference/engines/retrieve */ async getEngine(engine) { assert.strictEqual(typeof engine, 'string', 'engine must be a string'); return this._request('/engines/' + engine, {}, 'GET') .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * @typedef {Object} Completion * * @property {String} id * @property {String} object * @property {Number|null} created * @property {String} model * @property {array&lt;CompletionChoice>} choices * @see https://beta.openai.com/docs/api-reference/completions */ /** * @typedef {Object} CompletionBody * * @property {Number} [max_tokens] The maximum number of tokens to generate. * @property {Number} [temperature] What sampling temperature to use. * @property {Number} [top_p] An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. * @property {Number} [n] How many completions to generate for each prompt. * @property {Boolean} [stream] Whether to stream back partial progress. * @property {Number} [logprobs] Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. * @property {Boolean} [echo] Echo back the prompt in addition to the completion * @property {String|Array&lt;String>} [stop] Up to 4 sequences where the API will stop generating further tokens. * @property {Number} [presence_penalty] Number between 0 and 1 that penalizes new tokens based on whether they appear in the text so far. * @property {Number} [frequency_penalty] Number between 0 and 1 that penalizes new tokens based on their existing frequency in the text so far. * @property {Number} [best_of] Generates best_of completions server-side and returns the "best" (the one with the lowest log probability per token). * @property {Object} [logit_bias] Modify the likelihood of specified tokens appearing in the completion. * @see https://beta.openai.com/docs/api-reference/completions */ /** * @typedef {Object} CompletionChoice * * @property {String} text * @property {Number} index * @property {Number|null} logprobs * @property {String} finish_reason * @see https://beta.openai.com/docs/api-reference/completions */ /** * Creates a new completion for the provided prompt and parameters. * @param {string|array} [prompt=&lt;|endoftext|>] The prompt(s) to generate completions for, encoded as a string, a list of strings, or a list of token lists. * @param {CompletionBody} [body={}] * @returns {Promise&lt;Completion>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * var prompt = 'My name is Bond'; * client.complete(prompt, {stop: ['\n', '"'], temperature: 0}) * .then(completion => { * console.log(`Result: ${prompt}${completion.choices[0].text}`); * }) * .catch(console.error); * * @see https://beta.openai.com/docs/api-reference/completions/create */ async complete(prompt, body = {}) { assert.ok(typeof prompt === 'string' || Array.isArray(prompt), 'prompt must be a string or array'); assert.ok(typeCheck(parameters.completion, body), 'invalid body content'); if (body.engine) { var engine = body.engine; delete body.engine; } return this._request(`/engines/${engine || this.engine}/completions`, {prompt, ...body}) .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * @typedef {Object} Search * * @property {Number} document * @property {String} object * @property {Number} score * @see https://beta.openai.com/docs/api-reference/searches */ /** * @typedef {Object} SearchBody * * @property {Array&lt;String>} [documents] Up to 200 documents to search over, provided as a list of strings. * @property {String} [file] The ID of an uploaded file that contains documents to search over. * @property {Number} [max_rerank] The maximum number of documents to be re-ranked and returned by search. * @property {Boolean} [return_metadata] A special boolean flag for showing metadata. * @see https://beta.openai.com/docs/api-reference/searches */ /** * Given a query and a set of documents or labels, the model ranks each document based on its semantic similarity to the provided query. * @param {string|array} query * @param {SearchBody} [body={}] * @returns {Promise&lt;Search>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * const documents = ['Dancing', 'Programming', 'Skating', 'Drawing']; * * client.search('I do not like CSS', {documents}) * .then(result => { * var max_score = Math.max(...result.map(e => e.score), 0); * * console.log(`Likely subject: ${documents[result.find(e => e.score === max_score).document]} (${max_score})`); * }) * .catch(console.error); * * @see https://beta.openai.com/docs/guides/search/create */ async search(query, body = {}) { assert.strictEqual(typeof query, 'string', 'query must be a string'); assert.ok(typeCheck(parameters.search, body), 'invalid body content'); if (body.engine) { var engine = body.engine; delete body.engine; } return this._request(`/engines/${engine || this.engine}/search`, {query, ...body}) .then(res => res.data.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * @typedef {Object} Classification * * @property {String|Completion} completion * @property {String} label * @property {String} model * @property {String} object * @property {String} search_model * @property {String} [prompt] * @property {Array&lt;ClassificationExample>} selected_examples * @see https://beta.openai.com/docs/api-reference/classifications */ /** * @typedef {Object} ClassificationBody * * @property {Array&lt;Array&lt;String>>} [examples] A list of examples with labels. * @property {String} [file] The ID of the uploaded file that contains training examples. * @property {Array&lt;String>} [labels] The set of categories being classified. * @property {String} [search_model] ID of the engine to use for Search. * @property {Number} [temperature] What sampling temperature to use. * @property {Number} [logprobs] Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. * @property {Number} [max_examples] The maximum number of examples to be ranked by Search when using file. * @property {Object} [logit_bias] Modify the likelihood of specified tokens appearing in the completion. * @property {Boolean} [return_prompt] If set to true, the returned JSON will include a "prompt" field containing the final prompt that was used to request a completion. * @property {Boolean} [return_metadata] A special boolean flag for showing metadata. * @property {Array&lt;String>} [expand] If an object name is in the list, we provide the full information of the object; otherwise, we only provide the object ID. * @see https://beta.openai.com/docs/api-reference/classifications */ /** * @typedef {Object} ClassificationExample * * @property {Number} document * @property {String} label * @property {String} text * @see https://beta.openai.com/docs/api-reference/classifications */ /** * [BETA] Classifies the specified query using provided examples. * @param {string|array} query * @param {ClassificationBody} [body={}] * @returns {Promise&lt;Classification>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * const examples = [ * ['A happy moment', 'Positive'], * ['I am sad.', 'Negative'], * ['I am feeling awesome', 'Positive'] * ]; * * const labels = ['Positive', 'Negative', 'Neutral']; * * client.classificate('It is a raining day :(', {examples, labels, 'search_model': 'ada', 'engine': 'curie'}) * .then(classification => { * console.log(`Classification: ${classification.label}`); * }) * .catch(console.error); * * @see https://beta.openai.com/docs/api-reference/classifications/create */ async classificate(query, body = {}) { assert.strictEqual(typeof query, 'string', 'query must be a string'); assert.ok(typeCheck(parameters.classification, body), 'invalid body content'); if (body.model) { var model = body.model; delete body.model; } return this._request(`/classifications`, {model: model || this.engine, query, ...body}) .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * @typedef {Object} Answer * * @property {Array&lt;String>} answers * @property {String|Completion} completion * @property {String} model * @property {String} object * @property {String} search_model * @property {String} [prompt] * @property {Array&lt;AnswerDocument>} selected_documents * @see https://beta.openai.com/docs/api-reference/answers */ /** * @typedef {Object} AnswerBody * * @property {Array&lt;Array&lt;String>>} examples List of (question, answer) pairs that will help steer the model towards the tone and answer format you'd like. * @property {String} examples_context A text snippet containing the contextual information used to generate the answers for the examples you provide. * @property {Array&lt;String>} [documents] List of documents from which the answer for the input question should be derived. * @property {String} [file] The ID of an uploaded file that contains documents to search over. * @property {String} [search_model] ID of the engine to use for Search. * @property {Boolean} [return_prompt] If set to true, the returned JSON will include a "prompt" field containing the final prompt that was used to request a completion. * @property {Array&lt;String>} [expand] If an object name is in the list, we provide the full information of the object; otherwise, we only provide the object ID. * @property {Number} [max_rerank] The maximum number of documents to be ranked by Search when using file. * @property {Boolean} [return_metadata] A special boolean flag for showing metadata. * @property {Number} [max_tokens] The maximum number of tokens allowed for the generated answer. * @property {Number} [temperature] What sampling temperature to use. * @property {Number} [n] How many answers to generate for each question. * @property {Number} [logprobs] Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. * @property {String|Array&lt;String>} [stop] Up to 4 sequences where the API will stop generating further tokens. * @property {Object} [logit_bias] Modify the likelihood of specified tokens appearing in the completion. * @see https://beta.openai.com/docs/api-reference/answers */ /** * @typedef {Object} AnswerDocument * * @property {Number} document * @property {String} text * @see https://beta.openai.com/docs/api-reference/answers */ /** * [BETA] Answers the specified question using the provided documents and examples. * @param {string|array} question * @param {AnswerBody} [body={}] * @returns {Promise&lt;Answer>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * const documents = ['Puppy A is happy.', 'Puppy B is sad.']; * const examples_context = 'In 2017, U.S. life expectancy was 78.6 years.'; * const examples = [ * ['What is human life expectancy in the United States?', '78 years.'] * ]; * * const stop = ['\n', '&lt;|endoftext|>']; * * client.answer('Which puppy is happy?', {documents, examples_context, examples, stop}) * .then(answer => { * console.log(`Answer: ${answer.answers[0]}`); * }) * .catch(console.error); * * @see https://beta.openai.com/docs/api-reference/answers/create */ async answer(question, body = {}) { assert.strictEqual(typeof question, 'string', 'question must be a string'); assert.ok(typeCheck(parameters.answer, body), 'invalid body content'); if (body.model) { var model = body.model; delete body.model; } return this._request(`/answers`, {model: model || this.engine, question: question, ...body}) .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * @typedef {Object} File * * @property {String} id * @property {String} object * @property {Number} bytes * @property {Number|null} created_at * @property {String} filename * @property {String} purpose * @property {String} status * @property {String|null} status_details * @see https://beta.openai.com/docs/api-reference/files */ /** * Returns a list of files that belong to the user's organization. * @returns {Promise&lt;Array&lt;File>>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * client.getFiles() * .then(console.log) * .catch(console.error); * @see https://beta.openai.com/docs/api-reference/files/list */ async getFiles() { return this._request('/files', {}, 'GET') .then(res => res.data.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * Returns information about a specific file. * @param {String} filename * @returns {Promise&lt;File>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * client.getFile('FILE_ID') * .then(console.log) * .catch(console.error); * @see https://beta.openai.com/docs/api-reference/files/retrieve */ async getFile(fileId) { assert.strictEqual(typeof fileId, 'string', 'fileId must be a string'); return this._request('/files/' + fileId, {}, 'GET') .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * @typedef {Object} DeletedFile * * @property {String} id * @property {String} object * @property {Boolean} deleted * @see https://beta.openai.com/docs/api-reference/files */ /** * Delete a File. * @param {String} fileId * @returns {DeletedFile} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * client.deleteFile('FILE_ID') * .then(console.log) * .catch(console.error); * @see https://beta.openai.com/docs/api-reference/files/delete */ async deleteFile(fileId) { assert.strictEqual(typeof fileId, 'string', 'fileId must be a string'); return this._request('/files/' + fileId, {}, 'DELETE') .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * Upload a file that contains document(s) to be used across various endpoints/features. * @param {string|ReadStream} file The content of the JSON to be uploaded. * @param {String} purpose The intended purpose of the uploaded documents. * @returns {File} * @example * const fs = require('fs'); * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * client.uploadFile(fs.createReadStream('file.jsonl'), 'answers') * .then(console.log) * .catch(console.error); * * client.uploadFile('{"text": "A text here"}', 'answers') * .then(console.log) * .catch(console.error); * @see https://beta.openai.com/docs/api-reference/files/upload */ async uploadFile(file, purpose) { assert.ok(typeof file === 'string' || file instanceof stream.Readable, 'file must be a string or readableStream'); assert.strictEqual(typeof purpose, 'string', 'purpose must be a string'); assert.ok(purpose === 'search' || purpose === 'answers' || purpose === 'classifications', 'invalid purpose'); if (typeof file === 'string') { let content = file; file = new stream.Readable(); file.push(content); file.push(null); file.path = 'file.jsonl'; } let data = new FormData(); data.append('file', file); data.append('purpose', purpose); return this._request('/files', data, 'POST', data.getHeaders()) .then(res => res.data) .catch(err => { throw new RequestError(err.response.data.error); }); } /** * Split text by keys. * @param {String} text The string to be encoded * @returns {Array&lt;String>} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * var encoded = client.encode('Hello, world!'); * console.log(encoded); * @see https://beta.openai.com/docs/introduction/key-concepts */ encode(text) { assert.strictEqual(typeof text, 'string', 'text must be a string'); return gpt3encoder.encode(text); } /** * Decode keys to text. * @param {Array&lt;String>} text The encoded text * @returns {string} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * var encoded = client.encode('Hello, world!'); * var decoded = client.decode(encoded); * console.log(`Decoded: ${decoded}`); * @see https://beta.openai.com/docs/introduction/key-concepts */ decode(encoded_text) { assert.ok(Array.isArray(encoded_text), 'encoded_text must be an array'); return gpt3encoder.decode(encoded_text); } /** * Shows the token amount of the inserted text. * @param {String} text The string to get the token amount * @returns {Number} * @example * const OpenAI = require('openai-nodejs'); * const client = new OpenAI('YOUR_API_KEY'); * * var tokens = client.tokens('Hello, world!'); * console.log(`Tokens count: ${tokens}`); * @see https://beta.openai.com/docs/introduction/key-concepts */ tokens(text) { assert.strictEqual(typeof text, 'string', 'text must be a string'); return this.encode(text).length; } } module.exports = OpenAI;</code></pre> </article> </section> </div> </main> <footer class="layout-footer"> <div class="container"> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.7</a> </div> </footer> <script src="scripts/prism.dev.js"></script> </body> </html>