Issue with OpenAI's Rate Limit 429 Restriction

I've been experimenting with this repository in order to implement semantic search for YouTube videos using OpenAI + Pinecone. However, I keep encountering a 429 error at the following step - "Run the command npx tsx src/bin/process-yt-playlist.ts to pre-process the transcripts and fetch embeddings from OpenAI, then insert them into a Pinecone search index."

Any assistance would be greatly appreciated!

Here is my openai.ts file

import pMap from 'p-map'
import unescape from 'unescape'

import * as config from '@/lib/config'

import * as types from './types'

import pMemoize from 'p-memoize'
import pRetry from 'p-retry'
import pThrottle from 'p-throttle'

// TODO: enforce max OPENAI_EMBEDDING_CTX_LENGTH of 8191

// https://platform.openai.com/docs/guides/rate-limits/what-are-the-rate-limits-for-our-api
// TODO: enforce TPM
const throttleRPM = pThrottle({
  // 3k per minute instead of 3.5k per minute to add padding
  limit: 3000,
  interval: 60 * 1000,
  strict: true
})

type PineconeCaptionVectorPending = {
  id: string
  input: string
  metadata: types.PineconeCaptionMetadata
}

export async function getEmbeddingsForVideoTranscript({
  transcript,
  title,
  openai,
  model = config.openaiEmbeddingModel,
  maxInputTokens = 100, // TODO???
  concurrency = 1
}: {
  transcript: types.Transcript
  title: string
  openai: types.OpenAIApi
  model?: string
  maxInputTokens?: number
  concurrency?: number
}) {
  const { videoId } = transcript

  let pendingVectors: PineconeCaptionVectorPending[] = []
  let currentStart = ''
  let currentNumTokensEstimate = 0
  let currentInput = ''
  let currentPartIndex = 0
  let currentVectorIndex = 0
  let isDone = false

  // const createEmbedding = pMemoize(throttleRPM(createEmbeddingImpl))

  // Pre-compute the embedding inputs, making sure none of them are too long
  do {
    isDone = currentPartIndex >= transcript.parts.length

    const part = transcript.parts[currentPartIndex]
    const text = unescape(part?.text)
      .replaceAll('[Music]', '')
      .replaceAll(/[\t\n]/g, ' ')
      .replaceAll('  ', ' ')
      .trim()
    const numTokens = getNumTokensEstimate(text)

    if (!isDone && currentNumTokensEstimate + numTokens < maxInputTokens) {
      if (!currentStart) {
        currentStart = part.start
      }

      currentNumTokensEstimate += numTokens
      currentInput = `${currentInput} ${text}`

      ++currentPartIndex
    } else {
      currentInput = currentInput.trim()
      if (isDone && !currentInput) {
        break
      }

      const currentVector: PineconeCaptionVectorPending = {
        id: `${videoId}:${currentVectorIndex++}`,
        input: currentInput,
        metadata: {
          title,
          videoId,
          text: currentInput,
          start: currentStart
        }
      }

      pendingVectors.push(currentVector)

      // reset current batch
      currentNumTokensEstimate = 0
      currentStart = ''
      currentInput = ''
    }
  } while (!isDone)
  let index = 0;

  console.log("Entering embeddings calculation")
  // Evaluate all embeddings with a max concurrency
  // const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
  const vectors: types.PineconeCaptionVector[] = await pMap(
    pendingVectors,
    async (pendingVector) => {
      // await delay(6000); // add a delay of 1 second before each iteration
      console.log(pendingVector.input + " " + model)


      // const { data: embed } = await openai.createEmbedding({
      //   input: pendingVector.input,
      //   model
      // })

      async function createEmbeddingImpl({
        input = pendingVector.input,
        model = 'text-embedding-ada-002'
      }: {
        input: string
        model?: string
      }): Promise<number[]> {
        const res = await pRetry(
          () =>
            openai.createEmbedding({
              input,
              model
            }),
          {
            retries: 4,
            minTimeout: 1000,
            factor: 2.5
          }
        )
      
        return res.data.data[0].embedding
      }

      const embedding = await pMemoize(throttleRPM(createEmbeddingImpl));
      

      const vector: types.PineconeCaptionVector = {
        id: pendingVector.id,
        metadata: pendingVector.metadata,
        values: await embedding(pendingVector)
      }
      console.log(index + " THIS IS THE NUMBER OF CALLS TO OPENAI Embedding: " + embedding)
      index++;
      return vector
    },
    {
      concurrency
    }
  )

  return vectors
}

function getNumTokensEstimate(input: string): number {
  const numTokens = (input || '')
    .split(/\s/)
    .map((token) => token.trim())
    .filter(Boolean).length

  return numTokens
}

I have attempted to increase the time gap between API calls well below the allowable limit, but I am still confronted with the same issue.

Answer №1

If your OpenAI account runs out of credits, a 429 Rate Limit error will be sent to you. I had previously been utilizing free credits that had a 3-month expiration date. To keep track of your available credits, visit the Usage page:

On a side note, once I added a credit card to my account, it took approximately 5 minutes for the rate limit issue to be resolved.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking for help with setting up Nodemailer and installing it via NPM

I am currently developing a mobile application using Ionic with Angular/Typescript, and I'm in need of a front-end solution to dynamically send emails in the background to a specific email address. I tried using emailjs, but it requires JavaScript whi ...

What is the best way to design functions that can return a combination of explicit types and implicit types?

When looking at the code provided below, function system(): ISavable & ISerializable { return { num: 1, // error! save() {}, load() {}, serialize() {}, deserialize() {}, } } interface ISavable { sa ...

Abrupt surge in Firestore read operations detected in Next.js application following a period of no modifications - refer to the accompanying visual

https://i.sstatic.net/vim7m.png During the initial 10 days of working on the project, I noticed a consistent range of reads between 100 - 300 per day while regularly refreshing documents from firestore. Days 11-15 were spent away from the project visiting ...

Learn how to transfer information (specifically, 2 strings) from a next.js server to a node.js server, followed by the necessary steps to modify the values on the node.js server

Forgive me if I lack knowledge in this area, as I am relatively new to using JS and have limited experience with servers/APIs. Currently, I am working on implementing nextauth.js to authenticate users' Twitter accounts for a sign-in feature on an app ...

Choose only the options that are present in both arrays

I am working on creating a multiple select feature that displays all nodes, but only checks the ones that are present in 2 arrays. My front end is developed using Angular 8 and TypeScript. private mountSelect(nodesInRelation, lineApiKey) { console.lo ...

Despite implementing a no-store cache in Next JS 13.4, the page fails to refresh its data

In my Next JS 13.4 app, I am utilizing the app route feature and fetching data from an API with the option to cache set as no-store. export const getBooks = () => new Promise(async (resolve, reject) => { const response = await fetch(process.env.API ...

Show image using Typescript model in Angular application

In my Angular (v8) project, I have a profile page where I typically display the user's photo using the following method: <img class="profile-user-img" src="./DemoController/GetPhoto?Id={{rec.Id}}" /> However, I am considering an alternative ap ...

What is the best way to incorporate an interface in TypeScript that is both callable and has properties?

Given the scenario where an interface is defined as: interface FooWithBar { ():void; bar():void; } I am struggling with writing the implementation. I attempted the following: function foo(){ } foo.bar = function(){ }; This approach did not wo ...

How can the default scrolling feature be disabled for all NextJS <Link>s?

Currently, I am in the process of creating a website using NextJS and incorporating a fade-in and fade-out page transition. In order to maintain a smooth user experience, I have implemented a manual scroll to the top of the page between these transitions t ...

Encountering issues with fs.readFileSync when used within a template literal

For some reason, I am encountering an error when trying to read a file using fs.readFileSync within a Template literal. The specific error message that I'm getting is: Error: ENOENT: no such file or directory, open './cookie.txt' at Obje ...

Is there a way to operate both websocket and http methods concurrently on a server in Typescript?

I have a question regarding running a websocket server with the route "ws://localhost:port" using the 'ws' library. It requires the app instance of 'express' and also features http routes such as "http://localhost:port/auth/login". I am ...

Implementing Firebase-triggered Push Notifications

Right now, I am working on an app that is built using IONIC 2 and Firebase. In my app, there is a main collection and I am curious to know if it’s doable to send push notifications to all users whenever a new item is added to the Firebase collection. I ...

The attribute 'X' is not present in the specified type 'IntrinsicAttributes & InferPropsInner'

I've been restructuring my code from a .js file to a .tsx file, as seen below: import React, { useEffect, useState } from 'react' import PropTypes from 'prop-types' import { checkMobile } from '../../utils/common' import ...

Display real-time information in angular material table segment by segment

I need to incorporate service data into an Angular mat table with specific conditions as outlined below: If the difference between the start date and end date is less than 21 days, display 'dd/mm' between the 'start_date' and 'end ...

Is the getStaticProps function executed on the server side?

I'm trying to grasp the concept of build time in terms of when it affects the page rendering process versus when it's involved in compiling the app into a Vercel URL. ...

Create a hierarchical tree structure using a string separated by dots

I am struggling with organizing a tree structure. :( My goal is to create a tree structure based on the interface below. export type Tree = Array<TreeNode>; export interface TreeNode { label: string; type: 'folder' | 'file'; ...

Typescript Syntax for Inferring Types based on kind

I'm struggling to write proper TypeScript syntax for strict type inference in the following scenarios: Ensuring that the compiler correctly reports any missing switch/case options Confirming that the returned value matches the input kind by type typ ...

React - the use of nested objects in combination with useState is causing alterations to the initial

After implementing radio buttons to filter data, I noticed that when filtering nested objects, the originalData is being mutated. Consequently, selecting All again does not revert back to the original data. Can anyone explain why both filteredData and orig ...

Tips for showing the upcoming week in an angular application

Could someone please assist me with displaying the dates for the next 7 days using TypeScript? I am familiar with obtaining the date for the 7th day ahead, but I am unsure on how to generate a list of the 7 consecutive days. ...

Establish a table containing rows derived from an object

I am currently dealing with a challenge in creating a table that contains an array of nested objects. The array I have follows this schema: array = [ { id: 'Column1', rows: { row1: 'A', row2 ...