openai-python icon indicating copy to clipboard operation
openai-python copied to clipboard

Supplying API keys per request

Open numpde opened this issue 2 years ago • 5 comments

I'd like to supply the API key for each request separatly (for different users of the same app), instead of openai.api_key = ....

I find this strange behaviour, as documented in the following code, see in particular the _UNEXPECTED_BEHAVIOR tests. Edit: the following tests all pass with openai==0.25.0.

import os
import openai
import unittest

from openai.error import AuthenticationError, RateLimitError

# No API key is provided implicitly, to avoid leakage
assert os.environ.get('OPENAI_API_KEY') is None

# This is my API key
MINE = os.environ['MY_OPENAI_API_KEY']

prompt = "Give me three anagrams of 'Randompile':"


class NoKeyError(Exception):
    pass


def inspector(f):
    def _(*a, **kw):
        try:
            result = f(*a, **kw)
        except RateLimitError:
            raise RuntimeError("This test assumes the API key is still valid.")
        except AuthenticationError as ex:
            if "No API key provided" in ex.user_message:
                raise NoKeyError
            else:
                raise
        else:
            return result

    return _


@inspector
def completion(*, key_constr=None, key_member=None):
    worker = openai.Completion(api_key=key_constr)
    return worker.create(api_key=key_member, model='text-davinci-003', prompt=prompt)


@inspector
def dalleimage(*, key_constr=None, key_member=None):
    worker = openai.Image(api_key=key_constr)
    return worker.create(api_key=key_member, prompt=prompt)


class ObservedBehavior(unittest.TestCase):
    def test_completion_00(self):
        with self.assertRaises(NoKeyError):
            completion(key_constr=None, key_member=None)

    def test_completion_10_UNEXPECTED_BEHAVIOUR(self):
        with self.assertRaises(NoKeyError):
            completion(key_constr=MINE, key_member=None)

    def test_completion_01(self):
        result = completion(key_constr=None, key_member=MINE)
        # print(f"{prompt}", result['choices'][0]['text'].strip(), sep='\n')

    def test_completion_11(self):
        result = completion(key_constr=MINE, key_member=MINE)
        # print(f"{prompt}", result['choices'][0]['text'].strip(), sep='\n')

    def test_dalleimage_00(self):
        with self.assertRaises(NoKeyError):
            dalleimage(key_constr=None, key_member=None)

    def test_dalleimage_10_UNEXPECTED_BEHAVIOUR(self):
        with self.assertRaises(NoKeyError):
            dalleimage(key_constr=MINE, key_member=None)

    def test_dalleimage_01_UNEXPECTED_BEHAVIOUR(self):
        with self.assertRaises(NoKeyError):
            dalleimage(key_constr=None, key_member=MINE)

    def test_dalleimage_11_UNEXPECTED_BEHAVIOUR(self):
        with self.assertRaises(NoKeyError):
            dalleimage(key_constr=MINE, key_member=MINE)


if __name__ == '__main__':
    unittest.main()

numpde avatar Dec 22 '22 12:12 numpde

Thanks @numpde !

I'm a little confused by this issue. Can you elaborate a bit more on what you'd expect to see in the different test cases?

hallacy avatar Dec 22 '22 17:12 hallacy

Basically, I'd expect

openai.Image(api_key=api_key).create(...)

or

openai.Image.create(api_key=api_key, ...)

to work, but they don't.

What I did to work-around was:

def create(**kw):
    worker = openai.Image()
    assert api_key
    worker.refresh_from({}, api_key=api_key)  # hammer it in
    return worker.request("post", worker._get_url("generations"), kw)

create(prompt=....)

numpde avatar Dec 22 '22 19:12 numpde

That makes sense. I've been able to recreate this behavior on Image.create but not on other API calls. Are there any other places you're seeing this issue?

hallacy avatar Dec 23 '22 17:12 hallacy

That makes sense. I've been able to recreate this behavior on Image.create but not on other API calls. Are there any other places you're seeing this issue?

I haven't tried (but seeing the code, I don't expect it).

numpde avatar Dec 23 '22 20:12 numpde

We probably won't be able to merge this in until after the holidays, but I think the patch above should fix your issue?

hallacy avatar Dec 23 '22 21:12 hallacy