本文章通过创建一个简单的聊天机器人,理解OpenAI中角色如何运作,如何维护记忆,并如何使用Gradio创建简单界面。
OpenAI API
角色
OpenAI语言模型中鲜为人知的功能之一是对话涉及多个角色。我们可以清楚的识别出“用户”和“助手”,但还有第三个角色“系统”,它能帮助我们更好地配置模型的行为。
这不仅适用于OpenAI模型,任何经过调优以用作聊天机器人的模型中都有这种角色,尽管它们不一定实现相同的角色,也不一定有相同的名称。
当我们使用诸如ChatGPT之类的工具时,我们始终扮演“用户”的角色。然而,API允许我们选择每个句子要发送给模型的角色。
以下是一个使用三种可用角色发送的消息列表的示例:
messages=[
{"role": "system", "content": "You work collecting orders in a delivery IceCream shop called
I'm freezed"},
{"role": "user", "content": "Hi, can i have an Ice Cream?"},
{"role": "assistant", "content": "Of course, any flavor in particular?."},
{"role": "user", "content": "Do you have Vainilla?"}
]
你看到的这种格式是特定于OpenAI的。每个模型系列都需要不同的格式,因此了解您要使用的模型的正确格式非常重要。
让我们更详细地了解OpenAI中的现有角色:
系统:我们可以告诉模型我们希望它如何行动,包括其个性和响应类型。此角色让我们配置模型的基本操作。随着时间的推移,它的重要性不断增加。GPT-4系列模型比之前的模型(如GPT-3.5)能更好地适应系统消息中接收到的指令。
用户:这些是来自用户想要发送的句子。
助手:这些是模型返回的响应。但作为程序员,您可以插入自己创建的助手消息。您现在可能不认为这很有用,但随着您对如何与大型语言模型一起工作的理解的深入,您将看到这是一种影响模型响应方式的方法。如果您提供一些示例响应,模型将倾向于模仿它们。
记忆
聊天机器人的一个真正关键的方面是其记忆,即其记住用户说过什么以及其回复的能力。实际上,没有一个大型语言模型天生具有这个功能——它没有记忆。这种记忆是需要我们在代码中实现的,我们需要存储整个对话并将其作为单个提示传递给模型。每次,模型都会阅读整个对话并生成新的响应。
在这篇文章中下,我们使用Gradio帮助我们维护记忆,或者对话的历史。
一次对话通常以初始系统消息开始,该消息指导模型如何行动以及其在对话中的角色。在本示例中,我们将创建一个在冰淇淋店中扮演销售员角色的聊天机器人。我们将在context
中指定角色和项目。
让我们看一个小例子,调用OpenAI,但不使用Gradio,只使用API来维护对话。
import openai==1.1.1
#创建上下文
context =[
{'role':'system', 'content':""" You work collecting orders in a delivery IceCream shop called
I'm freezed.
Our Menu:
-Vainilla.
-Chocolate.
-Lemon.
"""}]
#将上下文发送到openai并接收响应。
conversation = context
response = openai.ChatCompletion.create(
model="gpt-4o-mini",
messages=conversation)
#向用户显示响应。
print(response.choices[0].message["content"])
#将响应添加到池中。现在变量conversation包含
#上下文和第一个模型响应。
conversation.append(response)
#添加第二行,用户请求。
conversation.append({'role':'user', 'content':'A lemon IceCream, please.'})
#使用新行回调模型。现在conversation包含:
#上下文、第一个模型响应和第一个用户消息。
response = openai.ChatCompletion.create(
model="gpt-4o-mini",
messages=conversation)
上面的代码很简单:我们只需将对话行添加到变量conversation
中,一开始只包含context
,每次调用模型时将其传递给模型。模型实际上没有记忆!我们必须在我们的代码中集成记忆。
上面显示的代码只是一个示例。我们需要更好地组织它,这样每当用户想要添加新句子时,我们就不必编写新代码。
通过上面简要的解释,我们已经准备好开始创建我们的聊天机器人。
使用OpenAI和Gradio创建聊天机器人。
获取OpenAI密钥
首先,我们需要一个OpenAI账户来使用他们的服务。您可以在此页面找到有关OpenAI定价计划的所有必要信息:https://openai.com/pricing/。
获取OpenAI账户后,可以在此网址获取密钥:https://platform.openai.com/account/api-key。
安装依赖
需要安装两个库:OpenAI和Gradio。
#安装必要的库
pip install -q openai==1.1.1
pip install -q gradio==4.40.0
Gradio库旨在为机器学习解决方案轻松创建具有视觉吸引力的web界面,以促进演示的创建。它已被Hugging Face收购,成为在著名的Hugging Face Spaces中创建应用程序的常用工具。
导入依赖
import openai
import random
import gradio as gr
from getpass import getpass
openai.api_key=getpass("OpenAI API Key: ")
#model = "gpt-3.5-turbo"
model = "gpt-4o-mini"
作为一个模型,您可以使用OpenAI提供的任何模型。如您在代码中所见,我也保留了gpt-3.5-turbo模型,以便您进行测试,看看与当前的gpt-4o-mini有何区别。由于后者更强大且每个令牌的成本更低,因此它成为使用的最合乎逻辑的选择。
创建提示
让我们从创建提示开始。
#创建提示
context = [ {'role':'system', 'content':"""
You work collecting orders in a delivery IceCream shop called
I'm freezed.
First welcome the customer, in a very friedly way, then collects the order.
Your instuctions are:
-Collect the entire order, only from options in our menu, toppings included.
-Summarize it
-check for a final time if everithing is ok or the customer wants to add anything else.
-collect the payment, be sure to include topings and the size of the ice cream.
-Make sure to clarify all options, extras and sizes to uniquely
identify the item from the menu.
-Your answer should be short in a very friendly style.
Our Menu:
The IceCream menu includes only the flavors:
-Vainilla.
-Chocolate.
-Lemon.
-Strawberry.
-Coffe.
The IceCreams are available in two sizes:
-Big: 3$
-Medium: 2$
Toppings:
-Caramel
-White chocolate
-melted peanut butter
Each topping cost 0.5$
"""} ]
提示或context
分为两部分。
在第一部分中,我们指示模型应如何行动及其目标是什么。在本文中,指令是让它像一个冰淇淋店中的机器人一样行动,目标是找出用户想要什么口味。
在提示的第二部分中,我们提供了冰淇淋菜单的组成。
定义对话方法
现在,我们将定义两个方法,这些方法将包含对话记忆的逻辑,并与OpenAI API交互。
#此函数将接收对话中的不同消息,并调用OpenAI传递完整对话。
def continue_conversation(messages, temperature=0):
response = openai.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
)
return response.choices[0].message.content
这个方法非常简单;它只是调用OpenAI API来进行对话。
在方法内部,我们使用以下参数调用OpenAI:
model
:我们要使用的模型,在我们的例子中是gpt-4o-mini。
messages
:对话中的消息。
temperature
:介于0和2之间的数字值,表示模型在生成响应时可以具有多少想象力。值越低,模型的响应就越固定。
大语言生成模型并不总是对相同的输入给出相同的答案。temperature
越低,对于相同的输入,结果就越相似,通常情况下会重复自己。
模型会从一个单词列表中来选择使用哪个词来构建句子,每个词都会有一个概率值。例如,对于句子:“我的车是…”,模型可能返回以下单词列表:
快速 — 45%
红色 — 32%
旧的 — 20%
小的 — 3%
当temperature
为0,模型将始终返回单词“快速”。但随着temperature
的增加,选择另一个单词的机会将增加。
需要注意的是,temperature
过大不仅会增加创造性,还会增加模型的“幻觉”,这意味着它可能生成不那么准确或更无意义的响应。
现在让我们看一下将充当我们开发和Gradio之间桥梁的方法。方法的格式由Gradio指定,因此它必须包含两个参数:第一个接收用户当前消息,第二个接收对话及其全部历史,除了当前消息。
#Gradio将使用的函数。
def gradio_chat(message, history):
#将指令添加到提示中。
history_chat = context
#将Gradio发送给我们的历史添加到提示中。
for user, assistant in history:
history_chat.append({"role":"user", "content":user})
history_chat.append({"role":"assistant", "content":assistant})
#添加最后一个用户消息。
history_chat.append({"role":"user", "content":message})
#调用OpenAI并返回响应。
return continue_conversation(history_chat, 0)
这个方法要做的事情是将包含模型指令的context
作为对话的第一个消息引入。正如前文提到的,模型没有记忆,在每个消息中,必须发送其配置,以便它继续按照我们希望的方式行动。
接下来,使用从Gradio接收的包含对话的参数,按照OpenAI期望的格式构建对话。
要添加的最后一个消息是第一个参数中收到的消息,即用户要发送的新消息。
最后,调用我们之前创建的方法,传入history_char
变量中的完整对话,返回模型的响应。
定制界面
我使用了最简单Gradio函数:ChatInterface
来创建聊天机器人界面。ChatInterface
可以通过大量的参数,实现强大且高度可定制。您可以在此URL中查看参数的完整列表:https://www.gradio.app/docs/gradio/chatinterface。
#定制的gradio文本框。
InputText = gr.Textbox(label="order", info="Your Order here.", scale= 6)
gr.ChatInterface(gradio_chat,
textbox=InputText,
retry_btn=None,
undo_btn=None,
title="I'm freezed",
submit_btn="Order").launch()
在上面的代码中,提供了一个定制的文本框,指定不显示重试或撤销按钮,并为其提供了一个标题并更改了提交按钮的文本。
它接收的第一个参数是负责构建对话的函数,即之前创建的函数:gradio_chat
。
有了这些,我们已经准备就绪。这是其中一次对话的结果。
正如您所见,Gradio创建界面非常简单。
这篇文章简要介绍了如何通过OpenAI API创建简单聊天机器人的文章。最重要的是,理解了在所有聊天机器人中都存在的角色和记忆的概念。