使用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
相关产品推荐
相关产品推荐

