From 401 Errors to Timeouts with the OpenAI API

in #programming2 years ago

photo_2024-05-24_22-13-23.jpg

The above image was made by @amberjyang with Midjourney using the prompt 'a python and a holographic hourglass raining computer code.'

Background

Recently I wrote a proof-of-concept vector search app using pyscript. It takes any detailed question or description of any conspiracy-related topic as input and outputs a list of the most relevant news article summaries from the WantToKnow.info news archive. There are about 12,970 valid entries in the archive. Right now, the app looks at vectors of every one of these news articles and compares these to a vector computed from a user query to find a list of the most relevant items. I'd like to then feed these news items into gpt-4o to generate a summary brief of the material. To keep things secure, the user would input their OpenAI API key and click a button to generate and display the brief.

Revising everything

The other day I posted about hitting a roadblock with the OpenAI API. No matter what I did, I kept getting 401 forbidden errors when calling the API from my app. Eventually I became determined to run exactly the same request from my app as I'd successfully run in my Jupyter notebook. The version of pyscript I was building on (2023.5.1) didn't support this, but the newly released version (2024.5.1) seemed like it could work.

My code totally didn't work when I first tried it with 2024.5.1. The first big problem was that the class Element was no longer available to import from pyscript. There was zero documentation on this change that I could find. Eventually I decided just to reintroduce the class directly in my code, right after the imports. I found the class buried deep in the 2023.5.1 file and more or less just used it directly. Here's what it looks like now:

# Re-implementing the Element class
class Element:
    def __init__(self, element_id, element=None):
        self._id = element_id
        self._element = element

    @property
    def id(self):
        return self._id

    @property
    def element(self):
        """Return the dom element"""
        if not self._element:
            self._element = js.document.querySelector(f"#{self._id}")
        return self._element

    @property
    def value(self):
        return self.element.value

    @property
    def innerHtml(self):
        return self.element.innerHTML

    def write(self, value, append=False):
        if not append:
            self.element.innerHTML = value
        else:
            self.element.innerHTML += value

    def clear(self):
        if hasattr(self.element, "value"):
            self.element.value = ""
        else:
            self.write("", append=False)

    def select(self, query, from_content=False):
        el = self.element

        if from_content:
            el = el.content

        _el = el.querySelector(query)
        if _el:
            return Element(_el.id, _el)
        else:
            js.console.warn(f"WARNING: can't find element matching query {query}")

    def clone(self, new_id=None, to=None):
        if new_id is None:
            new_id = self.element.id

        clone = self.element.cloneNode(True)
        clone.id = new_id

        if to:
            to.element.appendChild(clone)
            # Inject it into the DOM
            to.element.after(clone)
        else:
            # Inject it into the DOM
            self.element.after(clone)

        return Element(clone.id, clone)

    def remove_class(self, classname):
        classList = self.element.classList
        if isinstance(classname, list):
            classList.remove(*classname)
        else:
            classList.remove(classname)

    def add_class(self, classname):
        classList = self.element.classList
        if isinstance(classname, list):
            classList.add(*classname)
        else:
            self.element.classList.add(classname)

That actually worked great. Now that I had Element back, I was free to enjoy the perks of the latest and greatest pyscript. I was able to install the openai and ssl packages, making it possible for me to do an API reqest from my app in exactly the same way as I'd done the successful API call from Jupyter. Here's how that looked:

async def send(event=None):
    userElement = js.document.getElementById('brief')
    OPENAI_API_KEY = userElement.value.strip()
    client = OpenAI(api_key=OPENAI_API_KEY, timeout=60.0,  max_retries=3)

    # Convert similar_items to string format
    global similar_items
    similar_items_str = ""
    for index, row in similar_items.iterrows():
        similar_items_str += f"Title: {row['Title']} Summary: {row['Summary']} Note: {row['Note']}"

    payload = f"Using br html tags instead of /n for line breaks, please generate a 500 word narrative summary of the following information: '''{similar_items_str}'''"

    chat_completion = client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": payload        }
    ],
    model="gpt-4o",
    )
    
    # Log the request data for debugging
    console.log(f"Data: {messages}")

    # Display the response in the summarybrief div
    Element('summarybrief').element.innerHTML = chat_completion

    # Debugging log
    console.log(reply)

Timeout

This request method didn't produce a 401 error, which was progress. But the request did time out every time I tried it. After reading a bunch of forums, I tried adding timeout=60.0, max_retries=3 but this did nothing. The timeout is happening almost instantly, leading me to believe that OpenAI's default 600ms timeout is being applied to my request. It's very likely that I'm not setting the timeout parameter correctly.

Another possibility is that pyscript is doing something to kill my request. The current state of the code seems to be something of a mystery and I couldn't find answers about this anywhere. So I joined the pyscript discord and asked about it. Hopefully someone there can help me. One way or another, I'm going to get this AI integration working. Eventually.


Read Free Mind Gazette on Substack

Read my novels:

See my NFTs:

  • Small Gods of Time Travel is a 41 piece Tezos NFT collection on Objkt that goes with my book by the same name.
  • History and the Machine is a 20 piece Tezos NFT collection on Objkt based on my series of oil paintings of interesting people from history.
  • Artifacts of Mind Control is a 15 piece Tezos NFT collection on Objkt based on declassified CIA documents from the MKULTRA program.
Sort:  

I really hope that I see the final results of all these codings cos I’m naive…

In the next week or two I should have a webpage up that you can try.

Congratulations @mada! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)

You published more than 950 posts.
Your next target is to reach 1000 posts.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP