你好,我是徐文浩。
过去的两讲,我带着你通过OpenAI提供的Embedding接口,完成了文本分类的功能。那么,这一讲里,我们重新回到Completion接口。而且这一讲里,我们还会快速搭建出一个有界面的聊天机器人来给你用。在这个过程里,你也会第一次使用 HuggingFace 这个平台。
HuggingFace 是现在最流行的深度模型的社区,你可以在里面下载到最新开源的模型,以及看到别人提供的示例代码。
ChatGPT来了,更快的速度更低的价格
我在第03讲里,已经给你看了如何通过Completion的接口,实现一个聊天机器人的功能。在那个时候,我们采用的是自己将整个对话拼接起来,将整个上下文都发送给OpenAI的Completion API的方式。不过,在3月2日,因为ChatGPT的火热,OpenAI放出了一个直接可以进行对话聊天的接口。这个接口叫做 ChatCompletion,对应的模型叫做gpt-3.5-turbo,不但用起来更容易了,速度还快,而且价格也是我们之前使用的 text-davinci-003 的十分之一,可谓是物美价廉了。
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
[reference_begin]注:点击在这个链接你可以看到接口调用示例。[reference_end]
在OpenAI的官方文档里,可以看到这个接口也非常简单。你需要传入的参数,从一段Prompt变成了一个数组,数组的每个元素都有role和content两个字段。
- role这个字段一共有三个角色可以选择,分别是 system 代表系统,user代表用户,而assistant则代表AI的回答。
- 当role是system的时候,content里面的内容代表我们给AI的一个指令,也就是告诉AI应该怎么回答用户的问题。比如我们希望AI都通过中文回答,我们就可以在content里面写“你是一个只会用中文回答问题的助理”,这样即使用户问的问题都是英文的,AI的回复也都会是中文的。
- 而当role是user或者assistant的时候,content里面的内容就代表用户和AI对话的内容。和我们在第03讲里做的聊天机器人一样,你需要把历史上的对话一起发送给OpenAI的接口,它才有能够理解整个对话的上下文的能力。
有了这个接口,我们就很容易去封装一个聊天机器人了,我把代码放在了下面,我们一起来看一看。
import openai
import os
openai.api_key = os.environ.get("OPENAI_API_KEY")
class Conversation:
def __init__(self, prompt, num_of_round):
self.prompt = prompt
self.num_of_round = num_of_round
self.messages = []
self.messages.append({"role": "system", "content": self.prompt})
def ask(self, question):
try:
self.messages.append({"role": "user", "content": question})
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=self.messages,
temperature=0.5,
max_tokens=2048,
top_p=1,
)
except Exception as e:
print(e)
return e
message = response["choices"][0]["message"]["content"]
self.messages.append({"role": "assistant", "content": message})
if len(self.messages) > self.num_of_round*2 + 1:
del self.messages[1:3] //Remove the first round conversation left.
return message
- 我们封装了一个Conversation类,它的构造函数 init 会接受两个参数,prompt 作为 system的content,代表我们对这个聊天