1、开发和应用准备: API key
chatgpt 的开发应用需要使用 API key。申请地址是:https://platform.openai.com/account/api-keys。
推荐给每个应用使用不同的 key。目前后台不会显示各个 key 的使用情况。但使用不同的 key ,可以当某个 key 不用或者被泄漏的时候,在后台直接废弃该 key ,而不会有更大范围的影响。
对于不同的应用,如何区分其使用量(如果涉及到费用结算)呢?目前 openai 不支持直接按照 key 分开显示使用量和费用。一个可粗略估计但仍然很麻烦的方法是通过 member ,在https://platform.openai.com/account/members可以为账户设置多个成员,然后在使用 API 时,在 API Key 前面加上你的名字,然后后台可以查看不同成员调用 API 的情况:
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: YOUR_NAME $OPENAI_API_KEY" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "Say this is a test!"}],
"temperature": 0.7
}'
2、如何调用 openai 的 API
openai 的 API 使用特别简单,直接 POST 到https://api.openai.com/v1/chat/completions即可:
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: $OPENAI_API_KEY" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "Say this is a test!"}],
"temperature": 0.7
}'
这里最重要的是-d
参数,就是提交的数据。里面可以定义若干参数:
- model :所使用的模型。用得比较多的是:
text-davinci-003
,即 GPT-3 ,效果差但速度快费用低、而且可以微调模型。gpt-3.5-turbo
,基本就是 chatgpt 现在的版本。gpt-4
,需要申请 API 权限并通过、效果最好但速度慢费用是 gpt-3.5 的 10 倍。
- messages :当前问题(若想连续对话,需要填上历史对话结果)。
- max_tokens: 回复的最大长度,默认为 16。
- n :返回回答条数,一般默认为 1 即可。
- stream :是否流式输出。默认为 false。若设置为 true , openai 将一个字一个字吐结果出来,类似于 chatgpt 上聊天的效果。
还有一些用来控制回答质量的参数:
- temperature : 0 到 2 的一个数值,默认为 1。越大结果约发散越有想象力创造力,越小结果越精确越确定。
- top_p :
- presence_penalty
- frequency_penalty
- logit_bias
这其中最重要的是 messasges 参数。它是一个列表,
"messages": [
{"role": "system", "content": "You are a helpful assistant!"},
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hello!"},
{"role": "user", "content": "who are you?"},
]
一般列表的第一项是prompt
,用来标记 AI 模型的角色,设置role
参数为system
。后面是历史对话和最新的问题。其中 role='user'
表示用户问题,role='assistant'
表示 AI 历史上的回答。你可以任意构造这种对话列表,并不需要该对话真实出现过。system 和 assistant 的字段也不是必须的。
3、处理 openai API 的返回值
openai API 的返回值是一个 JSON 对象,response.choices[0].message.content
即可读取 AI 的回答。
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nHello there, how may I assist you today?",
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 12,
"total_tokens": 21
}
}
如果调用 API 时设置了stream: true
, API 将返回多个 response ,每一个都可以像上面这样取出response.choices[0].delta.content
进行拼接(注意这里是 delta 字段不是 message 字段),直到response.choices[0].delta
为{}
为止(表示回复结束)。
4、openai 工具库
理论上,直接 curl 或者使用 requests 等库即可操作 openai 的 API ,但 openai 也提供了工具包,可以直接调用:
4.1、python 的 OPENAI 库
openai 提供了 python 的库,直接 pip 安装即可:
sudo -E pip install openai
使用也很简单,更多文档可参考https://github.com/openai/openai-python:
import openai
openai.api_key = "sk-..."
response = openai.ChatCompletion.create(
model='gpt-3.5-turbo',
messages=[
{'role': 'user', 'content': 'Count to 100, with a comma between each number and no newlines. E.g., 1, 2, 3, ...'}
],
temperature=0,
)
print(response.choices[0]["message"]["content"])
对于流式输出也很简单:
import openai
openai.api_key = "sk-..."
response = openai.ChatCompletion.create(
model='gpt-3.5-turbo',
messages=[
{'role': 'user', 'content': "What's 1+1? Answer in one word."}
],
temperature=0,
stream=True # this time, we set stream=True
)
for chunk in response:
print(chunk["choices[0]["delta"].get("content", ""))
4.2、javascript 的 OPENAI 库
openai 也提供了 javascript 库,直接 npm 安装即可:
sudo -E npm install -g openai
使用和 Python 版本差不多,更多文档可参考https://github.com/openai/openai-node:
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
const completion = await openai.createCompletion({
model: "text-davinci-003",
prompt: "Hello world",
});
console.log(completion.data.choices[0].text);
如果要实现流式输出等更高级的功能,可以用第三方封装的chatgpt api。
5、一些细节问题
5.1、代理问题
现在国内访问 openai 是双向受限的,首先 openai 的 chatgpt 不向国内提供服务,其次国内访问 openai 也存在访问不稳定的情况。
如果是在浏览器端访问 API ,直接开设浏览器代理即可。
如果在服务器端,一般的网络访问都支持https_proxy
环境变量:
export https_proxy=http://127.0.0.1:7890
如果是第三方库,库本身可能提供proxy
参数,具体参考库的文档。
5.2、token 是指什么
模型的宽度、输入、输出,包括计费的单位都是 token , token 是指 AI 模型里的基本单元。在英文中,它和单词并不完全一致,部分单词可能会被拆分成多个 token。平均一个 token 大约 4 个字符。但它和单词数量基本正相关,所以也可以简单认为就是单词数量(的 1.33 倍)。
每个中文字则被分割成 1 到 3 个 token ,平均是 2 个 token。也就是 1000 个汉字约需要 2000 个 token 的空间和花费。
openai 提供在线工具https://platform.openai.com/tokenizer用来查看 token 的分割和计数。python 包tiktoken可以编程实现查看 token 的分割和计数。
5.3、输入限制
文本模型都有一个模型宽度,单位是 token ,它是输入和输出的长度之和。gpt-3.5 的宽度是 4096 , gpt-4 是 8192。gpt-4 还有一个 32k 版本,模型宽度可达 32768。宽度越大,可供传入的输入就越大,能参考的历史聊天记录就越长。但 openai 根据实际的输入和输出总长度收费,输入越长,费用也将成倍增加。
5.4、API 收费
API 的使用是收费的,价格见https://openai.com/pricing。
对于 gpt-3.5 ,每一百万 token 输入和输出收费 2 美元。而 gpt-4 ,每一百万输入收费 30 美元,每一百万输出收费 60 美元。对于 32k 的 gpt-4 ,收费还需要加倍。
一个令人惊讶的事是, gpt-3 的 davinci 收费也高达 20 美元每 100 万字,是 gpt-3.5 的 10 倍。因此综合而言, gpt-3.5 是最合适的模型。
openai 的注册账户有 5 美元的免费额度。用完之后需要绑定信用卡来支付,不支持中国国内的信用卡。
在 https://platform.openai.com/account/usage可以看自己的使用量、花费以及余额,能细化到每一天。
5.5、连续对话功能
目前 GPT 模型,每次运行都是独立割裂的,并没有办法记住历史对话,你问一个问题,它完全独立地给一个答案。在某种意义上,现在的 GPT 模型是「死」的。正因如此,很多人认为 GPT 还不能算 AGI ( Artificial General Intelligence ,通用人工智能)。
但大家在使用过程中,却发现 GPT 可以记住上下文,可以连续对话。这是为什么呢?其实原因很简单,就是每个单独的对话,都把以前的历史记录给附上去,参考 API 的 messages 参数:
"messages": [
{"role": "system", "content": "You are a helpful assistant!"},
{"role": "user", "content": "I'm Jobs, who are you?"},
{"role": "assistant", "content": "Hello Jobs, I'm chatgpt."},
{"role": "user", "content": "How are you?"},
{"role": "assistant", "content": "Fine, thank you. And you?"},
{"role": "user", "content": "Do you know my name?"},
]
上面传入的列表,第一个是prompt
,接下来四个是历史问答,最后一个是具体要问的问题。模型每次回答问题时,都会将历史记录也作为输入的一部分,输出最终的回答。这样看上去像是能记住上下文,但其实有下面的限制:
- 历史记录也是输入的一部分,但模型的输入+输出也就是模型的宽度是有限制的。所以模型参考不了太长的历史记录,也就是参考不了太远的上下文。
- 每次都传入历史记录,会导致输入原来越长,而费用是要按照输入长度计费的,也就是多聊几次之后,每次问答的费用都很高。举个最夸张的例子, 32k 版本 gpt-4 模型,如果输入占满,每问一个问题就需要 32×0.06 也就是将近 2 美金, 14 人民币!
从这里也可以看出,这个历史记录不需要是真实的,用户可以自己编造对话列表, AI 也会照样读入然后输出回答。
5.6、绑定信用卡的问题
openai 用完免费额度之后,必须绑定信用卡来支付后续费用。绑定不支持国内信用卡,所以需要境外信用卡或者虚拟信用卡。
另外一个问题是在绑定过程中很容易出现「您的银行卡被拒绝了」的提示。主要原因是代理服务器使用的人太多,容易被认为有欺诈风险。解决办法是多尝试(目前暂未发现尝试会增加风险)。
https://scamalytics.com/ip可以用来检查一个 IP 是否干净,当然大部分 IP 都有风险,能在 60 分以下就算不错的了。
Q. E. D.