首页 > 其他分享 >【Gradio】Chatbot | 如何使用 Gradio Blocks 创建自定义聊天机器人

【Gradio】Chatbot | 如何使用 Gradio Blocks 创建自定义聊天机器人

时间:2024-06-23 23:56:59浏览次数:3  
标签:Blocks gr 自定义 Gradio 机器人 聊天 message chatbot history

简介

重要提示:如果您刚开始接触,我们建议使用 gr.ChatInterface 来创建聊天机器人——它是一个高级抽象,使得可以快速创建漂亮的聊天机器人应用程序,往往只需一行代码。在这里了解更多信息。

本教程将展示如何使用 Gradio 的低级 Blocks API 从头开始制作聊天机器人 UI。这将使您完全控制您的聊天机器人 UI。您将首先创建一个简单的聊天机器人来显示文本,第二个聊天机器人来流式传输文本响应,最后一个聊天机器人还可以处理媒体文件。我们创建的聊天机器人界面将如下所示:

0fc75080e9855e77966ba8cf2c34bd83.png

先决条件:我们将使用 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 来生成回应。

将流媒体添加到您的聊天机器人 

我们可以通过几种方式来改善上述聊天机器人的用户体验。首先,我们可以流式传输回应,这样用户就不必等待消息生成那么长时间。其次,我们可以让用户消息立即显示在聊天历史中,同时生成聊天机器人的回应。以下是实现该功能的代码:

7bb54715ce15f58602c4a940233b005d.png

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()

757fa5e716bee141945dbb09bb7f20a9.png

您会注意到,当用户提交他们的消息时,我们现在将三个事件与 .then() 链接起来:

  1. 第一种方法 user() 会用用户的消息更新聊天机器人,并清空输入字段。这个方法还会使输入字段变为非交互式的,这样用户在聊天机器人回应时就不能发送其他消息。因为我们希望这能立即发生,我们设置了 queue=False ,如果启用了队列,它将跳过任何队列。聊天机器人的历史记录中附加了 (user_message, None) , None 表示机器人尚未回应。

  2. 第二种方法, bot() 会用机器人的回应更新聊天机器人的历史记录。我们不是创建一个新消息,而是用机器人的回应替换之前创建的 None 消息。最后,我们逐个字符地构建消息,并且 yield 在它们被构建的过程中的中间输出。Gradio 会自动将任何带有 yield 关键字的函数转变为流输出接口。

  3. 第三种方法使输入字段再次变得互动,以便用户可以向机器人发送另一条消息。

当然,在实践中,你会用你自己更复杂的函数来替换 bot() ,这个函数可能会调用一个预训练的模型或者一个 API 来生成回应。

最后,我们通过运行 demo.queue() 来启用排队,这对于流式传输中间输出是必需的。您可以通过滚动到本页面顶部的演示来尝试改进后的聊天机器人。

喜欢/不喜欢聊天消息 

一旦您创建了您的 gr.Chatbot ,您就可以增加用户喜欢或不喜欢消息的功能。如果您希望用户对机器人的回复进行投票或标记不当的结果,这可能会很有用。

要将此功能添加到您的聊天机器人中,只需将一个 .like() 事件附加到您的聊天机器人即可。拥有 .like() 事件的聊天机器人将会在每条机器人消息旁边自动显示一个点赞图标和一个点踩图标。

.like() 方法要求您传入一个函数,当用户点击这些图标时会调用该函数。在您的函数中,应该有一个参数,其类型为 gr.LikeData 。Gradio 会自动为这个参数提供一个包含有关点赞或不喜欢消息的信息的对象。以下是一个简单的示例,展示如何让用户对聊天消息表示喜欢或不喜欢:

8353e89a4f3f491718af82b20dfff04f.png

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()

3f35a2704ddb406b3f3e6f4c68d09554.png

添加 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"])

将这些结合起来,我们可以创建一个多模态聊天机器人,它有一个多模态文本框,用户可以提交文本和媒体文件。代码的其余部分与之前大致相同:

a95fefb38243dd61c19195fc59abcce5.png

这段代码创建了一个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()  # 启动应用程序

1f988a11b9407a81aa34f2cdefbb7f2b.png

完成了!这就是构建聊天机器人模型界面所需的全部代码。最后,我们将在指南中附上一些在空间上运行的聊天机器人的链接,以便您了解还有哪些可能:

  • project-baize/Baize-7B:一个风格化的聊天机器人,允许您停止生成以及重新生成响应。

  • MAGAer13/mPLUG-Owl:一个多模态聊天机器人,允许您对回答进行点赞和点踩。

标签:Blocks,gr,自定义,Gradio,机器人,聊天,message,chatbot,history
From: https://blog.csdn.net/cxyhjl/article/details/139787962

相关文章

  • 使用fnm安装node,并自定义安装路径
    作者:咕魂时间:2024年6月23日本教程使用winget对fnm进行安装,主要分两部分,第一步安装fnm,第二步安装nodejs其中nodejs配置成功后只在powershell中生效1.fnm的安装假设我们自定义安装路径为:D:\fnm下载安装fnmwingetinstallSchniz.fnm--locationD:\fnm由于要从github上下......
  • Go自定义数据的序列化流程
    ......
  • 怎样利用 Clojure 的宏来创建自定义的控制结构,并且如何避免常见的错误?
    在Clojure中,宏是一种宏展开的机制,它可以用于创建自定义的控制结构。通过使用宏,你可以在编写代码时引入新的语法,从而使代码更具可读性和表达力。要创建一个宏,你需要使用defmacro宏,并将宏名称与一个参数列表和一个展开形式绑定。这个展开形式将在宏被调用时用于生成代码。......
  • 在IdentityServer4生成的JWT中添加一个自定义的Claim,用于ABP框架中要用到的token信息
    用过IdentityServer4或者熟悉ASP.NETCore认证的都应该知道有Claim,如何理解ids4中的Claim?这里可以理解为声明,我们每个用户都有多个Claim,每个Claim声明了用户的某个信息比如:Role=Admin,UserID=1000等等,这里Role,UserID每个都是用户的Claim,都是表示用户信息的单元 ,我们不妨把它称为......
  • 对比Vue2/Vue3项目如何自定义插件
    学习目标:对比Vue2/Vue3项目如何自定义插件学习内容:插件(Plugins)是一种能为Vue添加全局功能的工具代码。一个插件可以是一个拥有 install() 方法的对象,也可以直接是一个安装函数本身。安装函数会接收到安装它的应用实例传递给Vue.use()/ app.use() 的额外选项作......
  • SpringBoot+AOP+Redis自定义注解实现防重复提交
    1.哪些因素会引起重复提交?开发项目过程中可能会出现下面这些情况:前端下单按钮重复点击导致订单创建多次网速等原因造成页面卡顿,用户重复刷新提交请求黑客或恶意用户使用Postman等http工具重复恶意提交表单2.重复提交会带来哪些问题?重复提交带来的问题:会导致数据......
  • UE5笔记-实现Lumen实时渲染GI下的的类UCanvasRenderTarget实现多场景/自定义分辨率/方
    默认的SceneCapture不能用于实时Lumen光照模式下为了实现实时渲染GI下的的类似于UCanvasRenderTarget2D类.可以参考GameViewport类的源码尝试使用UE的渲染逻辑和数据多渲染一份视口副本到直接的FSceneView上,封装一份UCaptureRenderTarget出来从而实现一些例如自定义分辨率的......
  • 一文读懂Java线程池之自定义线程池、设置合适的线程数量、线程池阻塞队列、线程拒绝策
    在上篇我们学习了线程池各个参数的含义,线程池任务处理流程,使用线程池的好处等内容,本篇我们学习如何创建一个适合我们业务的线程池。为此,我们有必要先学习一下如何大概确定我们线程池核心线程数、怎么设置阻塞队列的类型与大小、当线程池没有能力处理任务了该如何使用拒绝策略等......
  • sqlalchemy根据字典kv自定义表结构
    根据数据的内容自动创建数据库表结构fromsqlalchemyimportcreate_engine,Column,Integer,String,Float,Booleanfromsqlalchemy.ext.declarativeimportdeclarative_basefromsqlalchemy.ormimportsessionmaker,Mapped,mapped_columnBase=declarative_base()......
  • 自定义组件获取接口数据
    <template><divclass="ting-title"><spanclass="text">{{text}}</span></div></template><script>exportdefault{name:'TingTitle',data:()=>{......