简介
重要提示:如果您刚开始接触,我们建议使用 gr.ChatInterface
来创建聊天机器人——它是一个高级抽象,使得可以快速创建漂亮的聊天机器人应用程序,往往只需一行代码。在这里了解更多信息。
本教程将展示如何使用 Gradio 的低级 Blocks API 从头开始制作聊天机器人 UI。这将使您完全控制您的聊天机器人 UI。您将首先创建一个简单的聊天机器人来显示文本,第二个聊天机器人来流式传输文本响应,最后一个聊天机器人还可以处理媒体文件。我们创建的聊天机器人界面将如下所示:
先决条件:我们将使用 gradio.Blocks
类来构建我们的聊天机器人演示。如果您还不熟悉它,可以先阅读 Blocks 指南。另外,请确保您使用的是 Gradio 的最新版本: pip install --upgrade gradio
。
一个简单的聊天机器人演示
让我们从重现上面的简单演示开始。你可能已经注意到,我们的机器人对任何输入只是随机回答“你好吗?”,“我爱你”,或者“我非常饿”。以下是用 Gradio 创建这个的代码:
import gradio as gr # 导入gradio库
import random # 导入random库,用于生成随机数
import time # 导入time库,用于控制时间相关的功能
# 使用gr.Blocks创建一个Gradio界面
with gr.Blocks() as demo:
chatbot = gr.Chatbot() # 创建一个聊天机器人组件
msg = gr.Textbox() # 创建一个文本框组件,用于用户输入消息
clear = gr.ClearButton([msg, chatbot]) # 创建一个清除按钮,用于清除文本框和聊天机器人的内容
# 定义一个响应函数,用于处理用户消息和聊天历史
def respond(message, chat_history):
# 机器人随机选择一条消息作为回复
bot_message = random.choice(
["How are you?", "I love you", "I'm very hungry"])
# 将用户消息和机器人消息添加到聊天历史中
chat_history.append((message, bot_message))
# 等待2秒钟
time.sleep(2)
# 返回空字符串和更新后的聊天历史
return "", chat_history
# 当文本框提交时,调用respond函数,并更新文本框和聊天机器人的内容
msg.submit(respond, [msg, chatbot], [msg, chatbot])
# 启动应用程序
demo.launch()
这里有三个 Gradio 组件:
一个
Chatbot
,它的值存储了用户和机器人之间对话的完整历史,作为响应对的列表。一个
Textbox
,用户可以在其中输入他们的消息,然后按回车/提交以触发聊天机器人的回应一个
ClearButton
按钮来清除文本框和整个聊天机器人的历史记录
我们有一个单一的函数, respond()
,它接收聊天机器人的整个历史记录,在记录中添加一个随机消息,等待2 秒钟,然后返回更新后的聊天历史。 respond()
函数在返回时也会清除文本框。
当然,在实践中,你会用你自己更复杂的函数来替换 respond()
,这个函数可能会调用一个预训练的模型或者一个 API 来生成回应。
将流媒体添加到您的聊天机器人
我们可以通过几种方式来改善上述聊天机器人的用户体验。首先,我们可以流式传输回应,这样用户就不必等待消息生成那么长时间。其次,我们可以让用户消息立即显示在聊天历史中,同时生成聊天机器人的回应。以下是实现该功能的代码:
import gradio as gr # 导入Gradio库
import random # 导入random库,用于生成随机回复
import time # 导入time库,用于控制延迟
# 使用Gradio的Blocks构建一个应用程序界面
with gr.Blocks() as demo:
chatbot = gr.Chatbot() # 创建一个聊天机器人组件
msg = gr.Textbox() # 创建一个文本框组件,用于用户输入消息
clear = gr.Button("Clear") # 创建一个按钮组件,用于清除聊天历史
# 定义一个函数,用于处理用户消息并更新聊天历史
def user(user_message, history):
return "", history + [[user_message, None]]
# 定义一个函数,用于生成机器人的回复并逐字符更新聊天历史
def bot(history):
bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
history[-1][1] = ""
for character in bot_message:
history[-1][1] += character
time.sleep(0.05) # 每个字符之间添加0.05秒的延迟
yield history
# 当用户提交消息时,先调用user函数,然后调用bot函数
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, chatbot, chatbot
)
# 当点击清除按钮时,清除聊天历史
clear.click(lambda: None, None, chatbot, queue=False)
# 启用队列功能
demo.queue()
# 启动应用程序
demo.launch()
您会注意到,当用户提交他们的消息时,我们现在将三个事件与 .then()
链接起来:
第一种方法
user()
会用用户的消息更新聊天机器人,并清空输入字段。这个方法还会使输入字段变为非交互式的,这样用户在聊天机器人回应时就不能发送其他消息。因为我们希望这能立即发生,我们设置了queue=False
,如果启用了队列,它将跳过任何队列。聊天机器人的历史记录中附加了(user_message, None)
,None
表示机器人尚未回应。第二种方法,
bot()
会用机器人的回应更新聊天机器人的历史记录。我们不是创建一个新消息,而是用机器人的回应替换之前创建的None
消息。最后,我们逐个字符地构建消息,并且yield
在它们被构建的过程中的中间输出。Gradio 会自动将任何带有yield
关键字的函数转变为流输出接口。第三种方法使输入字段再次变得互动,以便用户可以向机器人发送另一条消息。
当然,在实践中,你会用你自己更复杂的函数来替换 bot()
,这个函数可能会调用一个预训练的模型或者一个 API 来生成回应。
最后,我们通过运行 demo.queue()
来启用排队,这对于流式传输中间输出是必需的。您可以通过滚动到本页面顶部的演示来尝试改进后的聊天机器人。
喜欢/不喜欢聊天消息
一旦您创建了您的 gr.Chatbot
,您就可以增加用户喜欢或不喜欢消息的功能。如果您希望用户对机器人的回复进行投票或标记不当的结果,这可能会很有用。
要将此功能添加到您的聊天机器人中,只需将一个 .like()
事件附加到您的聊天机器人即可。拥有 .like()
事件的聊天机器人将会在每条机器人消息旁边自动显示一个点赞图标和一个点踩图标。
.like()
方法要求您传入一个函数,当用户点击这些图标时会调用该函数。在您的函数中,应该有一个参数,其类型为 gr.LikeData
。Gradio 会自动为这个参数提供一个包含有关点赞或不喜欢消息的信息的对象。以下是一个简单的示例,展示如何让用户对聊天消息表示喜欢或不喜欢:
import gradio as gr # 导入Gradio库
# 定义一个问候函数,它接收历史记录和用户输入,返回更新后的历史记录
def greet(history, input):
return history + [(input, "Hello, " + input)] # 将用户输入和问候语添加到历史记录中
# 定义一个投票函数,它接收点赞数据
def vote(data: gr.LikeData):
if data.liked:
print("You upvoted this response: " + data.value) # 如果用户点赞,打印点赞信息
else:
print("You downvoted this response: " + data.value) # 如果用户点踩,打印点踩信息
# 使用Gradio的Blocks创建一个新的应用程序
with gr.Blocks() as demo:
chatbot = gr.Chatbot() # 创建一个聊天机器人组件
textbox = gr.Textbox() # 创建一个文本框组件,用于用户输入消息
# 当用户在文本框中提交消息时,调用greet函数,并更新聊天机器人的内容
textbox.submit(greet, [chatbot, textbox], [chatbot])
# 为聊天机器人添加点赞/点踩功能
chatbot.like(vote, None, None) # 添加这行代码会在聊天机器人中显示点赞/点踩图标
# 启动应用程序
demo.launch()
添加 Markdown、图片、音频或视频
gr.Chatbot
组件支持部分 Markdown 语法,包括粗体、斜体和代码。例如,我们可以编写一个这样的函数,它对用户的消息作出响应,并用粗体显示“太酷了!”:
def bot(history):
response = "**That's cool!**"
history[-1][1] = response
return history
此外,它可以处理媒体文件,如图像、音频和视频。您可以使用 MultimodalTextbox
组件轻松地将所有类型的媒体文件上传到您的聊天机器人。要传入媒体文件,我们必须像这样将文件作为两个字符串的元组传入: (filepath, alt_text)
。 alt_text
是可选的,所以您也可以只传入一个元素的元组 (filepath,)
,像这样:
def add_message(history, message):
for x in message["files"]:
history.append(((x["path"],), None))
if message["text"] is not None:
history.append((message["text"], None))
return history, gr.MultimodalTextbox(value=None, interactive=False, file_types=["image"])
将这些结合起来,我们可以创建一个多模态聊天机器人,它有一个多模态文本框,用户可以提交文本和媒体文件。代码的其余部分与之前大致相同:
这段代码创建了一个Gradio聊天机器人,用户可以通过多模态文本框输入文本消息或上传文件,并且可以对聊天机器人的回复进行点赞或点踩。机器人的回复是预设的文本,并且支持流式文本,即字符会逐个显示,模拟打字效果。整个应用程序使用Gradio库构建,它允许快速创建交互式的机器学习或其他类型的应用程序。此外,应用程序支持队列功能,可以处理多个用户的请求。
import gradio as gr # 导入Gradio库,用于创建交互式应用程序
import os # 导入os库,用于操作系统功能,如文件路径操作
import time # 导入time库,用于控制时间相关的功能
# 这是一个多模态输入的聊天机器人演示,支持文本、Markdown、LaTeX、代码块、图片、音频和视频输入。同时展示了对流式文本的支持。
def print_like_dislike(x: gr.LikeData):
print(x.index, x.value, x.liked) # 定义一个函数,打印用户对聊天机器人回复的点赞或点踩的数据
def add_message(history, message):
for x in message["files"]: # 遍历消息中的文件
history.append(((x,), None)) # 将文件添加到历史记录中
if message["text"] is not None: # 如果消息中包含文本
history.append((message["text"], None)) # 将文本消息添加到历史记录中
return history, gr.MultimodalTextbox(value=None, interactive=False) # 返回更新后的历史记录和一个多模态文本框
def bot(history):
response = "**That's cool!**" # 定义机器人的响应文本
history[-1][1] = "" # 清空历史记录中最后一条消息的机器人回复部分
for character in response: # 遍历响应文本中的每个字符
history[-1][1] += character # 将字符逐个添加到机器人回复中
time.sleep(0.05) # 每添加一个字符后暂停0.05秒
yield history # 生成更新后的历史记录
with gr.Blocks() as demo: # 使用Gradio的Blocks创建一个新的应用程序
chatbot = gr.Chatbot(
[],
elem_id="chatbot",
bubble_full_width=False # 创建一个聊天机器人组件,设置不使用全宽度的气泡
)#创建一个Chatbot组件,用于显示聊天记录。初始聊天记录为空,设置元素ID为chatbot,并禁用气泡全宽显示
#创建一个MultimodalTextbox组件,用于用户输入。设置为可交互,允许上传图像文件,并设置占位符文本。
chat_input = gr.MultimodalTextbox(interactive=True, file_types=["image"], placeholder="Enter message or upload file...", show_label=False) # 创建一个多模态文本框,允许用户输入消息或上传文件
# 将chat_input的提交事件绑定到add_message函数,当用户提交输入时,调用add_message函数更新聊天记录。
chat_msg = chat_input.submit(add_message, [chatbot, chat_input], [chatbot, chat_input]) # 当用户提交消息时,调用add_message函数,并更新聊天机器人的内容
bot_msg = chat_msg.then(bot, chatbot, chatbot, api_name="bot_response") # 然后调用bot函数,生成机器人的响应
bot_msg.then(lambda: gr.MultimodalTextbox(interactive=True), None, [chat_input]) # 然后更新多模态文本框,以便用户可以继续输入
chatbot.like(print_like_dislike, None, None) # 为聊天机器人添加点赞/点踩功能
demo.queue() # 启用队列功能
demo.launch() # 启动应用程序
完成了!这就是构建聊天机器人模型界面所需的全部代码。最后,我们将在指南中附上一些在空间上运行的聊天机器人的链接,以便您了解还有哪些可能:
project-baize/Baize-7B:一个风格化的聊天机器人,允许您停止生成以及重新生成响应。
MAGAer13/mPLUG-Owl:一个多模态聊天机器人,允许您对回答进行点赞和点踩。