Skip to content

Instantly share code, notes, and snippets.

@beeman
Forked from AmazingTurtle/config.ts
Created July 8, 2021 06:00
Show Gist options
  • Select an option

  • Save beeman/e48d0f59e8b14b87c7d9c85ecd1583ca to your computer and use it in GitHub Desktop.

Select an option

Save beeman/e48d0f59e8b14b87c7d9c85ecd1583ca to your computer and use it in GitHub Desktop.

Revisions

  1. @AmazingTurtle AmazingTurtle created this gist Jul 7, 2021.
    5 changes: 5 additions & 0 deletions config.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    export const DEFAULT_ENGINE = 'davinci';
    export const ENGINE_LIST = ['ada', 'babbage', 'curie', 'davinci', 'davinci-instruct-beta', 'curie-instruct-beta'];
    export const ORIGIN = 'https://api.openai.com';
    export const DEFAULT_API_VERSION = 'v1';
    export const DEFAULT_OPEN_AI_URL = `${ORIGIN}/${DEFAULT_API_VERSION}`;
    569 changes: 569 additions & 0 deletions openai-client.d.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,569 @@
    export interface EngineResponse {
    id: string;
    object: 'engine';
    owner: string;
    ready: boolean;
    }

    export interface EnginesListResponse {
    data: Array<EngineResponse>;
    object: 'list';
    }

    export interface CreateCompletionRequest {
    /**
    * string or array Optional Defaults to <|endoftext|>
    *
    * The prompt(s) to generate completions for, encoded as a string, a list of strings, or a list of token lists.
    * Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.
    */
    prompt?: string | string[];

    /**
    * integer Optional Defaults to 16
    *
    * The maximum number of tokens to generate. Requests can use up to 2048 tokens shared between prompt and completion. (One token is roughly 4 characters for normal English text)
    */
    max_tokens?: number;

    /**
    * number Optional Defaults to 1
    *
    * What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer.
    * We generally recommend altering this or top_p but not both.
    */
    temperature?: number;

    /**
    * number Optional Defaults to 1
    *
    * An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.
    * We generally recommend altering this or temperature but not both.
    */
    top_p?: number;

    /**
    * integer Optional Defaults to 1
    *
    * How many completions to generate for each prompt.
    * Note: Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for max_tokens and stop.
    */
    n?: number;

    /**
    * boolean Optional Defaults to false
    *
    * Whether to stream back partial progress. If set, tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a data: [DONE] message.
    */
    stream?: boolean;

    /**
    * integer Optional Defaults to null
    *
    * Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. For example, if logprobs is 10, the API will return a list of the 10 most likely tokens. the API will always return the logprob of the sampled token, so there may be up to logprobs+1 elements in the response.
    */
    logprobs?: number;

    /**
    * boolean Optional Defaults to false
    *
    * Echo back the prompt in addition to the completion
    */
    echo?: boolean;

    /**
    * string or array Optional Defaults to null
    *
    * Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.
    */
    stop?: string | string[];

    /**
    * number Optional Defaults to 0
    *
    * Number between 0 and 1 that penalizes new tokens based on whether they appear in the text so far. Increases the model's likelihood to talk about new topics.
    */
    presence_penalty?: number;

    /**
    * number Optional Defaults to 0
    *
    * Number between 0 and 1 that penalizes new tokens based on their existing frequency in the text so far. Decreases the model's likelihood to repeat the same line verbatim.
    */
    frequency_penalty?: number;

    /**
    * integer Optional Defaults to 1
    *
    * Generates best_of completions server-side and returns the "best" (the one with the lowest log probability per token). Results cannot be streamed.
    * When used with n, best_of controls the number of candidate completions and n specifies how many to return – best_of must be greater than n.
    * Note: Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for max_tokens and stop.
    */
    best_of?: number;

    /**
    * map Optional Defaults to null
    *
    * Modify the likelihood of specified tokens appearing in the completion.
    * Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this tokenizer tool (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
    * As an example, you can pass {"50256": -100} to prevent the <|endoftext|> token from being generated.
    */
    logit_bias?: {[tokenId: string]: number};

    }

    export interface CreateCompletionViaGetRequest {
    /**
    * string or array Optional Defaults to <|endoftext|>
    *
    * The prompt(s) to generate completions for, encoded as a string, a list of strings, or a list of token lists.
    * Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.
    */
    prompt?: string | string[];

    /**
    * integer Optional Defaults to 16
    *
    * The maximum number of tokens to generate. Requests can use up to 2048 tokens shared between prompt and completion. (One token is roughly 4 characters for normal English text)
    */
    max_tokens?: number;

    /**
    * number Optional Defaults to 1
    *
    * What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer.
    * We generally recommend altering this or top_p but not both.
    */
    temperature?: number;

    /**
    * number Optional Defaults to 1
    *
    * An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.
    * We generally recommend altering this or temperature but not both.
    */
    top_p?: number;

    /**
    * integer Optional Defaults to 1
    *
    * How many completions to generate for each prompt.
    * Note: Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for max_tokens and stop.
    */
    n?: number;

    /**
    * integer Optional Defaults to null
    *
    * Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. For example, if logprobs is 10, the API will return a list of the 10 most likely tokens. the API will always return the logprob of the sampled token, so there may be up to logprobs+1 elements in the response.
    */
    logprobs?: number;

    /**
    * boolean Optional Defaults to false
    *
    * Echo back the prompt in addition to the completion
    */
    echo?: boolean;

    /**
    * string or array Optional Defaults to null
    *
    * Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.
    */
    stop?: string | string[];

    /**
    * number Optional Defaults to 0
    *
    * Number between 0 and 1 that penalizes new tokens based on whether they appear in the text so far. Increases the model's likelihood to talk about new topics.
    */
    presence_penalty?: number;

    /**
    * number Optional Defaults to 0
    *
    * Number between 0 and 1 that penalizes new tokens based on their existing frequency in the text so far. Decreases the model's likelihood to repeat the same line verbatim.
    */
    frequency_penalty?: number;

    /**
    * integer Optional Defaults to 1
    *
    * Generates best_of completions server-side and returns the "best" (the one with the lowest log probability per token). Results cannot be streamed.
    * When used with n, best_of controls the number of candidate completions and n specifies how many to return – best_of must be greater than n.
    * Note: Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for max_tokens and stop.
    */
    best_of?: number;

    /**
    * map Optional Defaults to null
    *
    * Modify the likelihood of specified tokens appearing in the completion.
    * Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this tokenizer tool (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
    * As an example, you can pass {"50256": -100} to prevent the <|endoftext|> token from being generated.
    */
    logit_bias?: {[tokenId: string]: number};

    }

    export interface Choice {

    text: string;
    index: number;
    logprobs: any;
    finish_reason: string;

    }

    export interface CreateCompletionResponse {
    id: string;
    object: 'text_completion';
    created: number;
    model: string;
    choices: Array<Choice>;
    }

    export interface CreateSearchRequestBase {

    /**
    * string Required
    * Query to search against the documents.
    */
    query: string;

    /**
    * Integer Optional Defaults to 200
    *
    * The maximum number of documents to be re-ranked and returned by search.
    * This flag only takes effect when file is set.
    */
    max_rerank?: number;

    /**
    * boolean Optional Defaults to false
    *
    * A special boolean flag for showing metadata. If set to true, each document entry in the returned JSON will contain a "metadata" field.
    * This flag only takes effect when file is set.
    */
    return_metadata?: boolean;

    }

    export interface CreateSearchRequestViaDocuments extends CreateSearchRequestBase {
    /**
    * string Required
    *
    * Up to 200 documents to search over, provided as a list of strings.
    * The maximum document length (in tokens) is 2034 minus the number of tokens in the query.
    */
    documents: Array<string>;
    }

    export interface CreateSearchRequestViaFile extends CreateSearchRequestBase {
    /**
    * string Required
    *
    * The ID of an uploaded file that contains documents to search over.
    */
    file: string;
    }

    export interface CreateSearchResponse {
    data: Array<{
    document: number;
    object: 'search_result';
    score: number;
    }>;
    object: 'list';
    }

    export interface CreateClassificationRequestBase {

    /**
    * string Required
    *
    * ID of the engine to use for completion.
    */
    model: string;

    /**
    * string Required
    *
    * Query to be classified.
    */
    query: string;

    /**
    * array Optional Defaults to null
    *
    * The set of categories being classified. If not specified, candidate labels will be automatically collected from the examples you provide. All the label strings will be normalized to be capitalized.
    */
    labels?: string[];

    /**
    * string Optional Defaults to ada
    *
    * ID of the engine to use for Search.
    */
    search_model?: string;

    /**
    * Optional Defaults to 0
    *
    * What sampling temperature to use. Higher values mean the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer.
    */
    temperature?: number;

    /**
    * Optional Defaults to null
    *
    * Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. For example, if logprobs is 10, the API will return a list of the 10 most likely tokens. the API will always return the logprob of the sampled token, so there may be up to logprobs+1 elements in the response.
    * When logprobs is set, completion will be automatically added into expand to get the logprobs.
    */
    logprobs?: number;

    /**
    * map Optional Defaults to null
    *
    * Modify the likelihood of specified tokens appearing in the completion.
    * Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this tokenizer tool (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
    * As an example, you can pass {"50256": -100} to prevent the <|endoftext|> token from being generated.
    */
    logit_bias?: {[tokenId: string]: number};

    /**
    * boolean Optional Defaults to false
    *
    * If set to true, the returned JSON will include a "prompt" field containing the final prompt that was used to request a completion. This is mainly useful for debugging purposes.
    */
    return_prompt?: boolean;

    /**
    * boolean Optional Defaults to false
    *
    * A special boolean flag for showing metadata. If set to true, each document entry in the returned JSON will contain a "metadata" field.
    * This flag only takes effect when file is set.
    */
    return_metadata?: boolean;

    /**
    * Optional Defaults to []
    *
    * If an object name is in the list, we provide the full information of the object; otherwise, we only provide the object ID. Currently we support completion and file objects for expansion.
    */
    expand?: Array<string>;
    }

    export interface CreateClassificationRequestViaExamples extends CreateClassificationRequestBase {
    /**
    * array Required
    *
    * A list of examples with labels, in the follwing format:
    * [["The movie is so interesting.", "Positive"], ["It is quite boring.", "Negative"], ...]
    * All the label strings will be normalized to be capitalized.
    */
    examples: Array<string>;
    }

    export interface CreateClassificationRequestViaFile extends CreateClassificationRequestBase {
    /**
    * string Required
    *
    * The ID of an uploaded file that contains documents to search over.
    */
    file: string;

    /**
    * integer Optional defaults to 200
    *
    * The maximum number of examples to be ranked by Search when using file. Setting it to a higher value leads to improved accuracy but with increased latency and cost.
    */
    max_examples?: number;
    }

    export interface CreateClassificationResponse {

    completion: string;
    label: string;
    model: string;
    object: 'classification';
    search_model: string;
    selected_examples?: Array<{
    document: number;
    text: string;
    }>;
    selected_documents?: Array<{
    document: number;
    text: string;
    }>;
    }

    export interface CreateAnswerRequestBase {

    /**
    * string Required
    *
    * ID of the engine to use for completion.
    */
    model: string;

    /**
    * string Required
    *
    * Question to get answered.
    */
    question: string;

    /**
    * array Required
    *
    * List of (question, answer) pairs that will help steer the model towards the tone and answer format you'd like. We recommend adding 2 to 3 examples.
    */
    examples: Array<string>;

    /**
    * string Required
    *
    * A text snippet containing the contextual information used to generate the answers for the examples you provide.
    */
    examples_context: string;

    /**
    * string Optional Defaults to ada
    *
    * ID of the engine to use for Search.
    */
    search_model?: string;

    /**
    * number Optional Defaults to 1
    *
    * What sampling temperature to use. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer.
    * We generally recommend altering this or top_p but not both.
    */
    temperature?: number;

    /**
    * integer Optional Defaults to null
    *
    * Include the log probabilities on the logprobs most likely tokens, as well the chosen tokens. For example, if logprobs is 10, the API will return a list of the 10 most likely tokens. the API will always return the logprob of the sampled token, so there may be up to logprobs+1 elements in the response.
    */
    logprobs?: number;

    /**
    * integer Optional Defaults to 16
    *
    * The maximum number of tokens to generate. Requests can use up to 2048 tokens shared between prompt and completion. (One token is roughly 4 characters for normal English text)
    */
    max_tokens?: number;

    /**
    * string or array Optional Defaults to null
    *
    * Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.
    */
    stop?: string | string[];

    /**
    * integer Optional Defaults to 1
    *
    * How many completions to generate for each prompt.
    * Note: Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for max_tokens and stop.
    */
    n?: number;

    /**
    * map Optional Defaults to null
    *
    * Modify the likelihood of specified tokens appearing in the completion.
    * Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this tokenizer tool (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
    * As an example, you can pass {"50256": -100} to prevent the <|endoftext|> token from being generated.
    */
    logit_bias?: {[tokenId: string]: number};

    /**
    * boolean Optional Defaults to false
    *
    * A special boolean flag for showing metadata. If set to true, each document entry in the returned JSON will contain a "metadata" field.
    * This flag only takes effect when file is set.
    */
    return_metadata?: boolean;

    /**
    * boolean Optional Defaults to false
    *
    * If set to true, the returned JSON will include a "prompt" field containing the final prompt that was used to request a completion. This is mainly useful for debugging purposes.
    */
    return_prompt?: boolean;

    /**
    * Optional Defaults to []
    *
    * If an object name is in the list, we provide the full information of the object; otherwise, we only provide the object ID. Currently we support completion and file objects for expansion.
    */
    expand?: Array<string>;
    }


    export interface CreateAnswerRequestViaDocuments extends CreateAnswerRequestBase {
    /**
    * array Required
    *
    * List of documents from which the answer for the input question should be derived. If this is an empty list, the question will be answered based on the question-answer examples.
    */
    documents: Array<string>;
    }

    export interface CreateAnswerRequestViaFile extends CreateAnswerRequestBase {
    /**
    * string Required
    *
    * The ID of an uploaded file that contains documents to search over.
    */
    file: string;

    /**
    * Integer Optional Defaults to 200
    *
    * The maximum number of documents to be re-ranked and returned by search.
    * This flag only takes effect when file is set.
    */
    max_rerank?: number;
    }

    export interface CreateAnswerResponse {

    answers: Array<string>;
    completion: string;
    model: string;
    object: 'answer';
    search_model: string;
    selected_documents: Array<{
    document: number;
    text: string;
    }>;

    }

    export type Purpose = 'search' | 'answers' | 'classifications';

    export interface OpenAIFile {

    id: string;
    object: 'file';
    bytes: number;
    created_at: number;
    filename: string;
    purpose: Purpose;

    }

    export interface ListFilesResponse {
    data: Array<OpenAIFile>;
    object: 'list';
    }

    export type UploadFileResponse = OpenAIFile;

    export type RetrieveFileResponse = OpenAIFile;
    168 changes: 168 additions & 0 deletions openai-client.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,168 @@
    import axios, {AxiosPromise, AxiosRequestConfig, Method} from 'axios';
    import FormData from 'form-data';
    import stream from 'stream';
    import {DEFAULT_API_VERSION, ORIGIN} from './config';
    import {
    CreateAnswerRequestViaDocuments,
    CreateAnswerRequestViaFile,
    CreateAnswerResponse,
    CreateClassificationRequestViaExamples,
    CreateClassificationRequestViaFile,
    CreateClassificationResponse,
    CreateCompletionRequest,
    CreateCompletionResponse,
    CreateCompletionViaGetRequest,
    CreateSearchRequestViaDocuments,
    CreateSearchRequestViaFile,
    CreateSearchResponse,
    EngineResponse,
    EnginesListResponse,
    ListFilesResponse,
    Purpose,
    RetrieveFileResponse,
    UploadFileResponse
    } from './types';

    export class OpenAI {

    constructor(private readonly apiKey: string, private readonly apiVersion: string = DEFAULT_API_VERSION) {
    }

    protected wrapAuthenticatedRequest<T = any>(url: string, method: Method, data: {} | FormData | undefined = undefined, axiosConfig: AxiosRequestConfig = {}): AxiosPromise<T> {
    function camelToUnderscore(key) {
    let result = key.replace(/([A-Z])/g, ' $1');
    return result.split(' ').join('_').toLowerCase();
    }

    return axios({
    ...axiosConfig,
    url,
    headers: {
    'Authorization': `Bearer ${this.apiKey}`,
    'Content-Type': 'application/json',
    ...(axiosConfig.headers || {})
    },
    data,
    method,
    });
    }

    protected assembleRequestUrl(relativeAddress: string): string {
    return `${ORIGIN}/${this.apiVersion}/${relativeAddress}`;
    }

    public engines = {
    _client: this,
    list(): AxiosPromise<EnginesListResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl('engines'),
    'GET',
    {}
    );
    },
    retrieve(engineId: string): AxiosPromise<EngineResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl(`engines/${engineId}`),
    'GET',
    {}
    );
    }
    };

    public completions = {
    _client: this,
    create(engineId: string, body: CreateCompletionRequest): AxiosPromise<CreateCompletionResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl(`engines/${engineId}/completions`),
    'POST',
    body
    );
    },
    createViaGet(engineId: string, body: CreateCompletionViaGetRequest): AxiosPromise<CreateCompletionResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl(`engines/${engineId}/completions/browser_stream`),
    'GET',
    body
    );
    },
    };

    public searches = {
    _client: this,
    create(engineId: string, body: CreateSearchRequestViaDocuments | CreateSearchRequestViaFile): AxiosPromise<CreateSearchResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl(`engines/${engineId}/search`),
    'POST',
    body
    );
    }
    };

    public classifications = {
    _client: this,
    create(body: CreateClassificationRequestViaExamples | CreateClassificationRequestViaFile): AxiosPromise<CreateClassificationResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl('classifications'),
    'POST',
    body
    );
    }
    };

    public answers = {
    _client: this,
    create(body: CreateAnswerRequestViaDocuments | CreateAnswerRequestViaFile): AxiosPromise<CreateAnswerResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl('answers'),
    'POST',
    body
    );
    }
    };

    public files = {
    _client: this,
    list(): AxiosPromise<ListFilesResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl('files'),
    'GET'
    );
    },
    upload(body: {
    file: string,
    purpose: Purpose
    }): AxiosPromise<UploadFileResponse> {
    const formData = new FormData();

    const file = new stream.Readable();

    file.push(body.file);
    file.push(null);
    (file as any).path = 'file.jsonl';

    formData.append('purpose', body.purpose);
    formData.append('file', file);
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl('files'),
    'POST',
    formData,
    {
    headers: formData.getHeaders()
    }
    );
    },
    retrieve(fileId: string): AxiosPromise<RetrieveFileResponse> {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl(`files/${fileId}`),
    'GET'
    );
    },
    delete(fileId: string): AxiosPromise {
    return this._client.wrapAuthenticatedRequest(
    this._client.assembleRequestUrl(`files/${fileId}`),
    'DELETE'
    );
    }
    };

    }