Call OpenAI API with Python requests is missing a model parameter
Question:
I’m trying to call OpenAI API from Python. I know they have their own openai
package, but I want to use a generic solution. I chose the requests
package for its flexibility. Here is my call
>>> headers = {"Authorization": "Bearer xxx"}
>>> url = 'https://api.openai.com/v1/completions'
>>> data = {'model': 'text-davinci-002', 'prompt': 'Once upon a time'}
>>> requests.get(url, headers=headers, data=data).content
... "error": {n "message": "you must provide a model parameter"
The header contains the API token. It’s correct, I tried it. I also tried to pass the same dictionary as json, as data but as a json string. Always the same error message. Any idea how to make the call?
Update:
>>> requests.get(url, headers=headers, json=data).content
>>> requests.get(url, headers=headers, json=json.dumps(data)).content
>>> requests.get(url, headers=headers, data=json.dumps(data)).content
>>> requests.get(url, headers=headers, data=json.dumps(data).encode()).content
These all return the same error. I tried to add 'Content-Type': 'application/json'
to the headers too.
update2:
It works for the completion endpoint with POST
, but not for the edit endpoint.
>>> completion_url = "https://api.openai.com/v1/completions"
>>> completion_data = {'model': 'text-davinci-002', 'prompt': 'Once upon a time'}
>>> requests.post(completion_url, headers=headers, json=completion_data).json()
... # it works
>>> edit_url = "https://api.openai.com/v1/edits"
>>> completion_data = {'model': 'text-davinci-002', 'input': 'Once upon a time', 'instruction': 'Continue'}
>>> requests.get(edit_url, headers=headers, json=edit_data).json()['error']['message']
'you must provide a model parameter'
>>> requests.post(edit_url, headers=headers, json=edit_data).json()['error']['message']
'Invalid URL (POST /v1/edits)'
Answers:
The API expects a JSON request body,not a form-encoded request. And, you need to use the requests.post()
method to send the right HTTP method.
Use the json
argument, not the data
argument, and the right method:
requests.post(url, headers=headers, json=data)
See the Create completion section of the OpenAI documentation, where the curl
source code sample posts JSON:
curl https://api.openai.com/v1/completions
-H 'Content-Type: application/json'
-H 'Authorization: Bearer YOUR_API_KEY'
-d '{
"model": "text-davinci-002",
"prompt": "Say this is a test",
"max_tokens": 6,
"temperature": 0
}'
as well as the More complicated POST requests section of the documentation:
Typically, you want to send some form-encoded data — much like an HTML form. To do this, simply pass a dictionary to the data
argument. Your dictionary of data will automatically be form-encoded when the request is made[.]
[…]
There are times that you may want to send data that is not form-encoded.
[…].
If you need [the application/json
header] set and you don’t want to encode the dict
yourself, you can also pass it directly using the json
parameter (added in version 2.4.2) and it will be encoded automatically[.]
(Bold emphasis mine, slightly edited for clarity).
Demo:
>>> import requests
>>> key = "<APIKEY>"
>>> headers = {"Authorization": f"Bearer {key}"}
>>> data = {'model': 'text-davinci-002', 'prompt': 'Once upon a time'}
>>> requests.post(url, headers=headers, json=data).json()
{'id': 'cmpl-6HIPWd1eDo6veh3FkTRsv9aJyezBv', 'object': 'text_completion', 'created': 1669580366, 'model': 'text-davinci-002', 'choices': [{'text': ' there was a castle up in space. In this castle there was a queen who', 'index': 0, 'logprobs': None, 'finish_reason': 'length'}], 'usage': {'prompt_tokens': 4, 'completion_tokens': 16, 'total_tokens': 20}}
The openai
Python library uses the requests library under the hood but takes care of details like how to send HTTP requests correctly for you.
I’m trying to call OpenAI API from Python. I know they have their own openai
package, but I want to use a generic solution. I chose the requests
package for its flexibility. Here is my call
>>> headers = {"Authorization": "Bearer xxx"}
>>> url = 'https://api.openai.com/v1/completions'
>>> data = {'model': 'text-davinci-002', 'prompt': 'Once upon a time'}
>>> requests.get(url, headers=headers, data=data).content
... "error": {n "message": "you must provide a model parameter"
The header contains the API token. It’s correct, I tried it. I also tried to pass the same dictionary as json, as data but as a json string. Always the same error message. Any idea how to make the call?
Update:
>>> requests.get(url, headers=headers, json=data).content
>>> requests.get(url, headers=headers, json=json.dumps(data)).content
>>> requests.get(url, headers=headers, data=json.dumps(data)).content
>>> requests.get(url, headers=headers, data=json.dumps(data).encode()).content
These all return the same error. I tried to add 'Content-Type': 'application/json'
to the headers too.
update2:
It works for the completion endpoint with POST
, but not for the edit endpoint.
>>> completion_url = "https://api.openai.com/v1/completions"
>>> completion_data = {'model': 'text-davinci-002', 'prompt': 'Once upon a time'}
>>> requests.post(completion_url, headers=headers, json=completion_data).json()
... # it works
>>> edit_url = "https://api.openai.com/v1/edits"
>>> completion_data = {'model': 'text-davinci-002', 'input': 'Once upon a time', 'instruction': 'Continue'}
>>> requests.get(edit_url, headers=headers, json=edit_data).json()['error']['message']
'you must provide a model parameter'
>>> requests.post(edit_url, headers=headers, json=edit_data).json()['error']['message']
'Invalid URL (POST /v1/edits)'
The API expects a JSON request body,not a form-encoded request. And, you need to use the requests.post()
method to send the right HTTP method.
Use the json
argument, not the data
argument, and the right method:
requests.post(url, headers=headers, json=data)
See the Create completion section of the OpenAI documentation, where the curl
source code sample posts JSON:
curl https://api.openai.com/v1/completions
-H 'Content-Type: application/json'
-H 'Authorization: Bearer YOUR_API_KEY'
-d '{
"model": "text-davinci-002",
"prompt": "Say this is a test",
"max_tokens": 6,
"temperature": 0
}'
as well as the More complicated POST requests section of the documentation:
Typically, you want to send some form-encoded data — much like an HTML form. To do this, simply pass a dictionary to the
data
argument. Your dictionary of data will automatically be form-encoded when the request is made[.][…]
There are times that you may want to send data that is not form-encoded.
[…].
If you need [the
application/json
header] set and you don’t want to encode thedict
yourself, you can also pass it directly using thejson
parameter (added in version 2.4.2) and it will be encoded automatically[.]
(Bold emphasis mine, slightly edited for clarity).
Demo:
>>> import requests
>>> key = "<APIKEY>"
>>> headers = {"Authorization": f"Bearer {key}"}
>>> data = {'model': 'text-davinci-002', 'prompt': 'Once upon a time'}
>>> requests.post(url, headers=headers, json=data).json()
{'id': 'cmpl-6HIPWd1eDo6veh3FkTRsv9aJyezBv', 'object': 'text_completion', 'created': 1669580366, 'model': 'text-davinci-002', 'choices': [{'text': ' there was a castle up in space. In this castle there was a queen who', 'index': 0, 'logprobs': None, 'finish_reason': 'length'}], 'usage': {'prompt_tokens': 4, 'completion_tokens': 16, 'total_tokens': 20}}
The openai
Python library uses the requests library under the hood but takes care of details like how to send HTTP requests correctly for you.