はじめに
ChatGPT APIの公開後、瞬く間に様々なサービスが誕生していますね。
私も少し触ってみましたが、マルコフ連鎖的に文章を紡ぐ仕組み上、レスポンスがやや遅い点が気になります。
PythonからAPIを叩いている多くの方はOpenAIのライブラリを使用しているかと思いますが、
一般的にHTTPリクエストに使用されるrequests
を使用すれば、ウェブサイト版のChatGPTとお話するときのように、逐次返答を受け取ることができます。
追記
openai
ライブラリでも普通にできました。後半で解説します。
方法
requests
のpost()
からAPIを叩いて、その際、引数とペイロードのstream
をTrue
にすればおkです。
以下の実装例の後半部分が該当箇所になります。
import requests, json
API_URL = "https://api.openai.com/v1/chat/completions"
API_KEY = "sk-************************************************"
def chat(text,
messages=None,
settings="",
max_tokens=2000,
temperature=1.,
top_p=.1,
presence_penalty=0.,
frequency_penalty=0.):
# やり取りの管理
messages = messages if messages is not None else []
if settings and not messages:
messages.append({"role": "system", "content": settings})
messages.append({'role': 'user', 'content': text})
# ヘッダ
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
# ペイロード
payload = {
"model": "gpt-3.5-turbo",
"messages": messages,
"max_tokens": max_tokens,
"temperature": temperature,
"top_p": top_p,
"presence_penalty": presence_penalty,
"frequency_penalty": frequency_penalty,
"stream": True,
}
# APIを叩く、streamをTrueに
resp = requests.post(API_URL, headers=headers, json=payload, stream=True)
# 返答を受け取り、逐次yield
response_text = ''
for chunk in resp.iter_lines():
try:
j = json.loads(chunk.decode()[6:])
content = j['choices'][0]['delta'].get('content')
if content:
response_text += content
yield content
except:
...
else: #
messages += [{'role': 'assistant', 'content': response_text}]
追記 openai
ライブラリでの方法
openai.ChatCompletion.create()
の引数stream
をTrue
にしてあげればおkです。
以下の実装例では上のrequests
の場合と同じ内容の関数にしてあります。
import openai
openai.api_key = "sk-************************************************"
def chat(text,
messages=None,
settings="",
max_tokens=2000,
temperature=1.,
top_p=.1,
presence_penalty=0.,
frequency_penalty=0.):
# やり取りの管理
messages = messages if messages is not None else []
if settings and not messages:
messages.append({"role": "system", "content": settings})
messages.append({'role': 'user', 'content': text})
# APIを叩く、streamをTrueに
resp = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
top_p=top_p,
presence_penalty=presence_penalty,
frequency_penalty=frequency_penalty,
stream=True
)
# 返答を受け取り、逐次yield
response_text = ""
for chunk in resp:
if chunk:
content = chunk['choices'][0]['delta'].get('content')
if content:
response_text += content
yield content
else: #
messages += [{'role': 'assistant', 'content': response_text}]
使い方
上記実装例ではyieldを使用し、ジェネレーターとして定義しているので、
messages = []
for talk in chat('こんにちは。自己紹介してください。', messages):
print(talk, end='')
さいごに
これを読んだ方が面白いサービスを作ってくれることを期待しています(他力本願)!