题意:使用 Python requests 调用 OpenAI API 时缺少 model 参数。
问题背景:
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
我正在尝试从 Python 调用 OpenAI API。我知道他们有自己的 openai
包,但我想使用一个通用的解决方案。我选择了 requests
包,因为它更灵活。下面是我的调用代码。
python">>>> 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?
请求头中包含了 API 令牌,是正确的,我已经测试过。我还尝试将相同的字典作为 JSON 或字符串传递,总是出现相同的错误信息。有什么办法可以让调用成功吗?
Update:
python">>>> 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.
这些方法都会返回相同的错误。我也尝试在请求头中添加 'Content-Type': 'application/json'
。
update2: It works for the completion endpoint with POST
, but not for the edit endpoint.
更新2:对于 completion 端点使用 POST 方法是可行的,但对 edit 端点无效。
python">>>> 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.
翻译为:
“API 期望接收的是 JSON 格式的请求体,而不是表单编码的请求。另外,你需要使用 `requests.post()` 方法来发送正确的 HTTP 请求。”
Use the json
argument, not the data
argument, and the right method:
使用 json
参数,而不是 data
参数,并确保使用正确的方法:
requests.post(url, headers=headers, json=data)
See the Create completion section of the OpenAI documentation, where the curl
source code sample posts JSON:
请参阅 OpenAI 文档的创建 completion 部分,其中的 curl 示例代码是通过 POST 方法发送 JSON 的:
python">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:
以及文档中的更复杂的 POST 请求部分:
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:
python">>>> 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.