Gradio 智能体 & MCP 黑客马拉松

获奖者
Gradio logo
  1. 聊天机器人
  2. 聊天机器人专属事件

聊天机器人专属事件

用户期望现代聊天机器人界面能够让他们轻松地与单个聊天消息互动:例如,用户可能想要重试消息生成、撤销消息,或者点击喜欢/不喜欢按钮来赞成或反对生成的消息。

值得庆幸的是,Gradio 聊天机器人暴露了多个事件,例如 `.retry`、`.undo`、`.like` 和 `.clear`,让你能够将此功能构建到你的应用程序中。作为应用程序开发者,你可以将函数附加到这些事件中的任何一个,从而允许你在用户与消息互动时运行任意 Python 函数。

在此演示中,我们将构建一个实现这些事件的用户界面。你可以在 Hugging Face Spaces 上查看我们部署的成品演示。

提示: `gr.ChatInterface` 会自动使用 `retry` 和 `.undo` 事件,因此最好从那里开始,以便快速获得一个完全可用的应用程序。

用户界面

首先,我们将构建一个不处理这些事件的用户界面,然后在此基础上进行构建。我们将使用 Hugging Face InferenceClient,以便在不设置任何 API 密钥的情况下开始使用。

这是我们应用程序的初稿

from huggingface_hub import InferenceClient
import gradio as gr

client = InferenceClient()

def respond(
    prompt: str,
    history,
):
    if not history:
        history = [{"role": "system", "content": "You are a friendly chatbot"}]
    history.append({"role": "user", "content": prompt})

    yield history

    response = {"role": "assistant", "content": ""}
    for message in client.chat_completion(
        history,
        temperature=0.95,
        top_p=0.9,
        max_tokens=512,
        stream=True,
        model="HuggingFaceH4/zephyr-7b-beta"
    ):
        response["content"] += message.choices[0].delta.content or ""

        yield history + [response]


with gr.Blocks() as demo:
    gr.Markdown("# Chat with Hugging Face Zephyr 7b 🤗")
    chatbot = gr.Chatbot(
        label="Agent",
        type="messages",
        avatar_images=(
            None,
            "https://em-content.zobj.net/source/twitter/376/hugging-face_1f917.png",
        ),
    )
    prompt = gr.Textbox(max_lines=1, label="Chat Message")
    prompt.submit(respond, [prompt, chatbot], [chatbot])
    prompt.submit(lambda: "", None, [prompt])


if __name__ == "__main__":
    demo.launch()

撤销事件

我们的撤销事件将用之前的用户消息填充文本框,并移除所有后续的助手回复。

为了获取最后一条用户消息的索引,我们可以像这样将 `gr.UndoData` 传递给我们的事件处理函数

def handle_undo(history, undo_data: gr.UndoData):
    return history[:undo_data.index], history[undo_data.index]['content']

然后我们将此函数传递给 `undo` 事件!

    chatbot.undo(handle_undo, chatbot, [chatbot, prompt])

你会注意到每个机器人回复现在都有一个“撤销图标”,你可以用它来撤销回复 -

undo_event

提示: 你也可以通过 `undo_data.value` 访问用户消息的内容

重试事件

重试事件的工作方式类似。我们将使用 `gr.RetryData` 获取上一条用户消息的索引,并从历史记录中移除所有后续消息。然后我们将使用 `respond` 函数生成新的回复。我们也可以通过 `gr.RetryData` 的 `value` 属性获取之前的提示。

def handle_retry(history, retry_data: gr.RetryData):
    new_history = history[:retry_data.index]
    previous_prompt = history[retry_data.index]['content']
    yield from respond(previous_prompt, new_history)

...

chatbot.retry(handle_retry, chatbot, chatbot)

你会看到机器人消息现在有一个“重试”图标 -

retry_event

提示: Hugging Face 推理 API 会缓存回复,因此在此演示中,重试按钮不会生成新的回复。

点赞事件

现在你应该能看到规律了!为了让用户点赞消息,我们将在聊天机器人中添加一个 `.like` 事件。我们将为其传递一个接受 `gr.LikeData` 对象的函数。在此情况下,我们只会打印被点赞或不喜欢的消息。

def handle_like(data: gr.LikeData):
    if data.liked:
        print("You upvoted this response: ", data.value)
    else:
        print("You downvoted this response: ", data.value)

...

chatbot.like(vote, None, None)

编辑事件

编辑监听器也是同样的想法!使用 `gr.Chatbot(editable=True)`,你可以捕获用户编辑。`gr.EditData` 对象会告诉我们被编辑消息的索引以及消息的新文本。下面,我们使用此对象来编辑历史记录,并删除任何后续消息。

def handle_edit(history, edit_data: gr.EditData):
    new_history = history[:edit_data.index]
    new_history[-1]['content'] = edit_data.value
    return new_history

...

chatbot.edit(handle_edit, chatbot, chatbot)

清除事件

作为额外内容,我们还将介绍 `.clear()` 事件,当用户点击清除图标以清除所有消息时,此事件会触发。作为开发者,你可以附加在此图标被点击时应发生的额外事件,例如处理额外聊天机器人状态的清除。

from uuid import uuid4
import gradio as gr


def clear():
    print("Cleared uuid")
    return uuid4()


def chat_fn(user_input, history, uuid):
    return f"{user_input} with uuid {uuid}"


with gr.Blocks() as demo:
    uuid_state = gr.State(
        uuid4
    )
    chatbot = gr.Chatbot(type="messages")
    chatbot.clear(clear, outputs=[uuid_state])

    gr.ChatInterface(
        chat_fn,
        additional_inputs=[uuid_state],
        chatbot=chatbot,
        type="messages"
    )

demo.launch()

在此示例中,当聊天历史记录通过垃圾桶图标被清除时,绑定到 `chatbot.clear` 事件的 `clear` 函数会向我们的会话状态返回一个新的 UUID。这可以在 `chat_fn` 函数中看到,该函数引用了我们会话状态中保存的 UUID。

此示例还展示了你可以通过传入自定义 `gr.Chatbot` 对象来将这些事件与 `gr.ChatInterface` 一起使用。

总结

就是这样!你现在知道如何为聊天机器人实现重试、撤销、点赞和清除事件了。