You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Gradio与GPT-3.5-turbo构建聊天机器人时显示字典键的问题

问题原因

Gradio的Chatbot组件要求的输入格式是由(用户消息, 助手消息)元组组成的列表,例如:

[(用户输入1, 助手回复1), (用户输入2, 助手回复2)]

而你的代码返回的是包含role和content的字典列表,不符合组件格式要求,所以会直接显示字典的键值结构。

解决方法

需要将传给Chatbot的历史记录转换成组件要求的元组格式,同时保留用于调用OpenAI的字典格式历史(存在State中),具体修改如下:

1. 修复全局变量冲突问题

原来的全局history和命令行输入system_msg会导致多用户访问时数据串用,改用Gradio的State组件管理对话历史,初始化时传入系统提示。

2. 修改predict函数

在函数中区分用于OpenAI调用的字典历史,和用于Gradio显示的元组历史:

def predict(input, history):
    # 截断历史:保留系统消息,删除最早的一组用户+助手对话
    if len(history) > 10:
        del history[1:3]
    
    # 添加用户输入到OpenAI用的历史
    history.append({"role": "user", "content": input})
    # 调用GPT-3.5-turbo
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=history)
    reply = response["choices"][0]["message"]["content"]
    # 添加助手回复到OpenAI用的历史
    history.append({"role": "assistant", "content": reply})
    
    # 转换为Chatbot需要的格式:跳过系统消息,配对用户和助手消息
    chat_display = []
    for i in range(1, len(history), 2):
        if history[i]["role"] == "user" and i+1 < len(history):
            chat_display.append((history[i]["content"], history[i+1]["content"]))
    
    # 返回显示用的历史,和用于后续调用的字典历史
    return chat_display, history

3. 调整完整代码

import openai
import gradio as gr

openai.api_key = "XXXXXXX"

# 初始化系统提示和对话历史
initial_system_msg = "You are a helpful assistant."
initial_history = [{"role": "system", "content": initial_system_msg}]

with open("chatbot.txt", "w") as f:
    f.write("System: "+initial_system_msg)

print("Say hello to your new assistant!")

def predict(input, history):
    if len(history) > 10:
        del history[1:3]
    
    history.append({"role": "user", "content": input})
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=history)
    reply = response["choices"][0]["message"]["content"]
    history.append({"role": "assistant", "content": reply})
    
    chat_display = []
    for i in range(1, len(history), 2):
        if history[i]["role"] == "user" and i+1 < len(history):
            chat_display.append((history[i]["content"], history[i+1]["content"]))
    
    return chat_display, history

with gr.Blocks() as demo:
    chatbot = gr.Chatbot()
    # 用初始化的带系统消息的历史作为State初始值
    state = gr.State(initial_history)
    
    with gr.Row():
        txt = gr.Textbox(show_label=False, placeholder="Type your message here...").style(container=False)
    
    txt.submit(predict, [txt, state], [chatbot, state])
    # 可选:添加清空聊天按钮
    gr.Button("Clear Chat").click(lambda: ([], initial_history), None, [chatbot, state])

demo.launch()

关键修改说明

  • 格式转换:遍历OpenAI用的字典历史,跳过系统消息,将用户和助手消息配对成元组,生成符合Chatbot要求的显示列表。
  • 历史截断优化:修正原代码的pop逻辑,只删除最早的用户+助手对话,保留系统提示。
  • 状态管理:用State组件存储对话历史,避免多用户访问时的数据冲突。
可选优化:Web界面设置系统提示

如果想让用户在网页上修改系统提示,可添加如下模块:

with gr.Blocks() as demo:
    # 添加系统提示设置区域
    with gr.Row():
        system_input = gr.Textbox(label="System Prompt", value="You are a helpful assistant.")
        set_system_btn = gr.Button("Set System Prompt")
    
    chatbot = gr.Chatbot()
    state = gr.State([])
    
    # 设置系统提示的函数
    def set_system_prompt(system_msg):
        new_history = [{"role": "system", "content": system_msg}]
        with open("chatbot.txt", "w") as f:
            f.write("System: "+system_msg)
        return [], new_history
    
    set_system_btn.click(set_system_prompt, system_input, [chatbot, state])
    
    # 原有的聊天输入区域
    with gr.Row():
        txt = gr.Textbox(show_label=False, placeholder="Type your message here...").style(container=False)
    
    txt.submit(predict, [txt, state], [chatbot, state])
    gr.Button("Clear Chat").click(lambda: ([], state.value if state.value else []), None, [chatbot, state])

demo.launch()

内容的提问来源于stack exchange,提问作者KnoBuddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:20:34